Skip to content

docs: add OpenCode setup guide#582

Merged
ding113 merged 5 commits intodevfrom
docs/opencode-usage
Jan 10, 2026
Merged

docs: add OpenCode setup guide#582
ding113 merged 5 commits intodevfrom
docs/opencode-usage

Conversation

@ding113
Copy link
Owner

@ding113 ding113 commented Jan 10, 2026

Summary

Add OpenCode CLI setup guide to the usage-doc page with full i18n support for 5 languages (zh-CN, zh-TW, en, ja, ru).

Problem

Users need documentation on how to configure OpenCode to work with cch as a unified OpenAI-compatible endpoint. There was no existing guide for OpenCode integration.

Related Issues:

Solution

Add a comprehensive OpenCode setup guide that includes:

  • Installation instructions for macOS, Linux, and Windows (multiple methods: script, Homebrew, npm, Chocolatey, Scoop)
  • Single opencode.json configuration example covering Claude (Haiku/Sonnet/Opus), GPT-5.2, and Gemini 3 (Pro/Flash)
  • Common troubleshooting tips
  • Model selection guidance

The guide is positioned in the CLI tools section after Gemini CLI and before Droid.

Changes

Core Changes

  • src/app/[locale]/usage-doc/page.tsx - Add OpenCode configuration and installation rendering functions
  • messages/*/usage.json (5 files) - Add i18n translations for OpenCode section

Supporting Changes

  • src/app/[locale]/usage-doc/_components/quick-links.tsx - Fix hardcoded Chinese text with i18n keys
  • src/app/[locale]/usage-doc/_components/toc-nav.tsx - Fix hardcoded Chinese text with i18n keys
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx - Add unit tests for OpenCode documentation

Testing

Automated Tests

  • Unit tests added covering:
    • OpenCode section ordering (after Gemini CLI, before Droid)
    • Configuration example content validation
    • i18n key presence for all 5 languages
  • Test coverage increased from 58.10% to 58.46% (statements)

Manual Testing

  1. Navigate to /[locale]/usage-doc
  2. Verify OpenCode section appears between Gemini CLI and Droid
  3. Verify configuration example displays correct cch endpoint and model IDs
  4. Switch between locales to verify translations

Checklist

  • Code follows project conventions
  • Self-review completed
  • Tests pass locally
  • i18n translations provided for all 5 supported languages

Description enhanced by Claude AI

@coderabbitai
Copy link

coderabbitai bot commented Jan 10, 2026

📝 Walkthrough

Walkthrough

在多语言使用文档中新增顶级 opencode 使用指南并在使用文档页面接入 OpenCode 的渲染与环境分支;若干组件文本替换为 i18n 调用;新增 OpenCode 相关单元测试文件并验证多语翻译键与示例内容。

Changes

Cohort / File(s) Change summary
多语言使用文档
messages/en/usage.json, messages/ja/usage.json, messages/ru/usage.json, messages/zh-CN/usage.json, messages/zh-TW/usage.json
添加顶级 opencode 对象(含 installationconfigurationstartupcommonIssues 等嵌套字段)。在 enruzh-CNzh-TW 中该 opencode 块出现两次(重复插入);ja 中添加一次。
使用文档页面与渲染逻辑
src/app/[locale]/usage-doc/page.tsx
CLIConfig 增加可选字段 requiresNodeJs?;将 UsageDocContent 导出;新增并集成 renderOpenCodeInstallation()renderOpenCodeConfiguration();将 opencode 作为一等 CLI 集成到平台渲染流,调整环境变量键名与环境准备分支。
国际化组件
src/app/[locale]/usage-doc/_components/quick-links.tsx, src/app/[locale]/usage-doc/_components/toc-nav.tsx
引入 useTranslations("usage") 并用翻译键替换若干硬编码中文文本(导航标签、返回顶部、目录空状态等)。
测试
tests/unit/usage-doc/opencode-usage-doc.test.tsx, tests/unit/usage-doc/usage-doc-page.test.tsx
新增 OpenCode 使用文档单元测试(验证文档顺序、示例 opencode.json 内容及多语言翻译键存在性);为 UsageDocPage 添加/调整测试以覆盖跳转/滚动与跳过链接渲染。

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR标题'docs: add OpenCode setup guide'清晰准确地总结了主要变更——添加OpenCode设置指南,与整个变更集高度相关。
Description check ✅ Passed PR描述详细说明了添加OpenCode CLI设置指南的目的、解决的问题、实现方案、代码变更和测试覆盖,与变更集完全相关。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch docs/opencode-usage

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ding113, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求的主要目的是扩展现有文档,为 OpenCode CLI 工具提供全面的设置和使用指南。通过引入新的文档页面和多语言支持,旨在降低用户入门门槛,并确保所有用户都能轻松配置和使用 OpenCode 与 cch 服务。同时,通过新增单元测试,进一步提升了代码质量和文档的准确性。

Highlights

  • 新增 OpenCode 设置指南: 在文档中添加了 OpenCode 的配置与安装教程,详细介绍了在 macOS、Linux 和 Windows 上的安装方法,以及如何连接 cch 服务进行配置。
  • 完善多语言支持: 为新增的 OpenCode 文档补齐了中文简体、中文繁体、英文、日文和俄文共五种语言的国际化(i18n)翻译。
  • 提供全面的 opencode.json 示例: 提供了一个包含 Claude (haiku/sonnet/opus)、GPT-5.2 和 Gemini 3 Pro/Flash 等模型的 opencode.json 配置文件示例,方便用户快速上手。
  • 提升单元测试覆盖率: 新增了单元测试,覆盖了 OpenCode 文档的显示顺序和示例内容,使整体代码覆盖率从 58.10% 提升至 58.46%。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions bot added documentation Improvements or additions to documentation area:i18n area:docs size/L Large PR (< 1000 lines) labels Jan 10, 2026
@github-actions
Copy link
Contributor

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

本次 PR 新增了 OpenCode 的配置与安装教程,并补齐了 5 种语言的 i18n 支持,同时添加了单元测试,整体工作非常出色。代码在功能上看起来是正确的,并且新增的测试覆盖了关键逻辑。

我主要在 page.tsx 中发现了一些可以提高代码可读性和可维护性的地方,具体请看我的评论。这些修改将使代码在未来更容易扩展和维护,尤其是在处理多个 CLI 工具的差异化逻辑时。

其他文件的修改(如 i18n JSON 文件和组件国际化)看起来都很棒。感谢你的贡献!

Comment on lines 1050 to 1074
const opencodeConfigJson = `{
"$schema": "https://opencode.ai/config.json",
"theme": "opencode",
"autoupdate": false,
"provider": {
"cch": {
"npm": "@ai-sdk/openai-compatible",
"name": "Claude Code Hub (cch)",
"options": {
"baseURL": "${resolvedOrigin}/v1",
"apiKey": "{env:CCH_API_KEY}"
},
"models": {
"claude-haiku-4-5-20251001": { "name": "Claude Haiku 4.5" },
"claude-sonnet-4-5-20250929": { "name": "Claude Sonnet 4.5" },
"claude-opus-4-5-20251101": { "name": "Claude Opus 4.5" },

"gpt-5.2": { "name": "GPT-5.2" },

"gemini-3-pro-preview": { "name": "Gemini 3 Pro Preview" },
"gemini-3-flash-preview": { "name": "Gemini 3 Flash Preview" }
}
}
}
}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

直接在代码中使用模板字符串来构建复杂的 JSON 对象容易因手误(如遗漏逗号、引号等)导致 JSON 格式错误,且不易维护。建议将这个配置定义为一个 JavaScript 对象,然后使用 JSON.stringify(obj, null, 2) 来生成格式化的 JSON 字符串。这样做更安全,也更易于阅读和修改。

    const opencodeConfig = {
      "$schema": "https://opencode.ai/config.json",
      theme: "opencode",
      autoupdate: false,
      provider: {
        cch: {
          npm: "@ai-sdk/openai-compatible",
          name: "Claude Code Hub (cch)",
          options: {
            baseURL: `${resolvedOrigin}/v1`,
            apiKey: "{env:CCH_API_KEY}",
          },
          models: {
            "claude-haiku-4-5-20251001": { name: "Claude Haiku 4.5" },
            "claude-sonnet-4-5-20250929": { name: "Claude Sonnet 4.5" },
            "claude-opus-4-5-20251101": { name: "Claude Opus 4.5" },
            "gpt-5.2": { name: "GPT-5.2" },
            "gemini-3-pro-preview": { name: "Gemini 3 Pro Preview" },
            "gemini-3-flash-preview": { name: "Gemini 3 Flash Preview" },
          },
        },
      },
    };
    const opencodeConfigJson = JSON.stringify(opencodeConfig, null, 2);

language="powershell"
code={`# 检查环境变量
echo $env:${cli.id === "codex" ? "CCH_API_KEY" : "ANTHROPIC_AUTH_TOKEN"}
echo $env:${cli.id === "codex" || cli.id === "opencode" ? "CCH_API_KEY" : "ANTHROPIC_AUTH_TOKEN"}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

这里的逻辑 cli.id === 'codex' || cli.id === 'opencode' 随着未来可能支持更多需要 CCH_API_KEY 的工具而变得越来越长。为了提高可读性和可维护性,建议将需要 CCH_API_KEYcli.id 列表提取出来,并使用 .includes() 来进行判断。

echo $env:${["codex", "opencode"].includes(cli.id) ? "CCH_API_KEY" : "ANTHROPIC_AUTH_TOKEN"}

language="bash"
code={`# 检查环境变量
echo $${cli.id === "codex" ? "CCH_API_KEY" : "ANTHROPIC_AUTH_TOKEN"}
echo $${cli.id === "codex" || cli.id === "opencode" ? "CCH_API_KEY" : "ANTHROPIC_AUTH_TOKEN"}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

这里的逻辑 cli.id === 'codex' || cli.id === 'opencode' 随着未来可能支持更多需要 CCH_API_KEY 的工具而变得越来越长。为了提高可读性和可维护性,建议将需要 CCH_API_KEYcli.id 列表提取出来,并使用 .includes() 来进行判断。

echo $${["codex", "opencode"].includes(cli.id) ? "CCH_API_KEY" : "ANTHROPIC_AUTH_TOKEN"}

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 file reviewed, no comments

Edit Code Review Agent Settings | Greptile

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (7)
messages/en/usage.json (1)

486-503: 优化安装选项的编号顺序

当前安装选项的编号与呈现顺序不一致:

  • Line 486: "Option 2: Homebrew" 出现在前面
  • Line 496: "Option 1: Official install script" 出现在后面
  • Line 501: "Option 3: npm" 出现在最后

建议将编号顺序与文档呈现顺序对齐,避免用户混淆。

♻️ 建议的修复
       "macos": {
         "description": "On macOS, install OpenCode using one of the following methods:",
         "homebrew": {
-          "title": "Option 2: Homebrew",
+          "title": "Option 1: Homebrew",
           "description": "Install via Homebrew:"
         }
       },

       "script": {
-        "title": "Option 1: Official install script",
+        "title": "Option 2: Official install script",
         "description": "Run the following command to install the latest version:"
       },

       "npm": {
-        "title": "Option 3: npm",
+        "title": "Option 3: npm (alternative)",
         "description": "Install globally via npm:"
       },
messages/zh-TW/usage.json (1)

482-498: 與英文版相同的選項編號問題

安裝方式的編號順序與呈現順序不一致:

  • Line 482: "方式二:Homebrew" 出現在前面
  • Line 492: "方式一:官方安裝腳本" 出現在後面
  • Line 497: "方式三:npm" 出現在最後

建議調整編號以匹配實際呈現順序。

messages/zh-CN/usage.json (1)

480-498: 调整安装方式的编号顺序

当前编号与呈现顺序不匹配:

  • Line 482: "方式二:Homebrew" 先出现
  • Line 492: "方式一:官方安装脚本" 后出现
  • Line 497: "方式三:npm" 最后出现

建议统一编号,使其与文档结构顺序一致,提升用户体验。

messages/ja/usage.json (1)

486-502: 与其他语言版本相同的编号顺序问题

安装方法的编号与呈现顺序不一致:

  • Line 486: "方法2:Homebrew" 出现在前
  • Line 496: "方法1:公式インストールスクリプト" 出现在后
  • Line 501: "方法3:npm" 出现在最后

建议调整编号使其与实际顺序匹配。

messages/ru/usage.json (1)

486-502: 与其他语言版本相同的编号顺序问题

安装方法的编号与呈现顺序不一致:

  • Line 486: "Способ 2: Homebrew" 出现在前
  • Line 496: "Способ 1: Официальный install-скрипт" 出现在后
  • Line 501: "Способ 3: npm" 出现在最后

建议调整编号使其与文档呈现顺序一致。

src/app/[locale]/usage-doc/page.tsx (2)

1002-1002: 冗余变量赋值。

const lang = os === "macos" ? "bash" : "bash"; 无论条件如何结果都是 "bash",应简化。

♻️ 建议修复
-    const lang = os === "macos" ? "bash" : "bash";
+    const lang = "bash";

1284-1307: 深层嵌套的三元表达式可读性较差。

随着 CLI 数量增加,三元表达式嵌套已达 5 层,建议考虑重构为对象映射以提高可维护性。此为可选优化,不影响当前功能。

♻️ 建议的重构方式
const startupKeys: Record<string, { title: string; desc: string; init: string }> = {
  "claude-code": {
    title: "claudeCode.startup.title",
    desc: "claudeCode.startup.description",
    init: "claudeCode.startup.initNote",
  },
  codex: {
    title: "codex.startup.title",
    desc: "codex.startup.description",
    init: "codex.startup.initNote",
  },
  opencode: {
    title: "opencode.startup.title",
    desc: "opencode.startup.description",
    init: "opencode.startup.initNote",
  },
  droid: {
    title: "droid.startup.title",
    desc: "droid.startup.description",
    init: "droid.startup.initNote",
  },
};

const keys = startupKeys[cli.id] ?? startupKeys.droid;
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

📥 Commits

Reviewing files that changed from the base of the PR and between 373220d and 98f04d2.

📒 Files selected for processing (9)
  • messages/en/usage.json
  • messages/ja/usage.json
  • messages/ru/usage.json
  • messages/zh-CN/usage.json
  • messages/zh-TW/usage.json
  • src/app/[locale]/usage-doc/_components/quick-links.tsx
  • src/app/[locale]/usage-doc/_components/toc-nav.tsx
  • src/app/[locale]/usage-doc/page.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

No emoji characters in any code, comments, or string literals

Files:

  • src/app/[locale]/usage-doc/_components/quick-links.tsx
  • src/app/[locale]/usage-doc/_components/toc-nav.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
  • src/app/[locale]/usage-doc/page.tsx
**/*.{ts,tsx,jsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,jsx,js}: All user-facing strings must use i18n (5 languages supported: zh-CN, en, ja, ko, de). Never hardcode display text
Use path alias @/ to map to ./src/
Use Biome for code formatting with configuration: double quotes, trailing commas, 2-space indent, 100 character line width
Prefer named exports over default exports
Use next-intl for internationalization
Use Next.js 16 App Router with Hono for API routes

Files:

  • src/app/[locale]/usage-doc/_components/quick-links.tsx
  • src/app/[locale]/usage-doc/_components/toc-nav.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
  • src/app/[locale]/usage-doc/page.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use React 19, shadcn/ui, Tailwind CSS, and Recharts for the UI layer

Files:

  • src/app/[locale]/usage-doc/_components/quick-links.tsx
  • src/app/[locale]/usage-doc/_components/toc-nav.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
  • src/app/[locale]/usage-doc/page.tsx
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Place unit tests in tests/unit/, integration tests in tests/integration/, and source-adjacent tests in src/**/*.test.ts

Files:

  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
🧠 Learnings (6)
📚 Learning: 2026-01-07T17:05:37.171Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-07T17:05:37.171Z
Learning: Applies to **/*.{ts,tsx,jsx,js} : Use next-intl for internationalization

Applied to files:

  • src/app/[locale]/usage-doc/_components/quick-links.tsx
  • src/app/[locale]/usage-doc/_components/toc-nav.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
📚 Learning: 2026-01-07T17:05:37.171Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-07T17:05:37.171Z
Learning: Applies to **/*.{ts,tsx,jsx,js} : All user-facing strings must use i18n (5 languages supported: zh-CN, en, ja, ko, de). Never hardcode display text

Applied to files:

  • src/app/[locale]/usage-doc/_components/quick-links.tsx
  • src/app/[locale]/usage-doc/_components/toc-nav.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
📚 Learning: 2026-01-10T06:20:04.478Z
Learnt from: NieiR
Repo: ding113/claude-code-hub PR: 573
File: src/actions/model-prices.ts:275-335
Timestamp: 2026-01-10T06:20:04.478Z
Learning: In the `ding113/claude-code-hub` repository, Server Actions (files under `src/actions/*.ts`) currently return hardcoded Chinese error messages directly. This is a codebase-wide architectural decision that applies to all action files (e.g., model-prices.ts, users.ts, system-config.ts). Changing this pattern requires a coordinated i18n refactor across all Server Actions, which should be handled as a separate unified task rather than piecemeal changes in individual PRs.

Applied to files:

  • src/app/[locale]/usage-doc/_components/quick-links.tsx
  • src/app/[locale]/usage-doc/_components/toc-nav.tsx
📚 Learning: 2026-01-05T03:02:14.502Z
Learnt from: NieiR
Repo: ding113/claude-code-hub PR: 539
File: src/app/[locale]/dashboard/_components/user/user-key-table-row.tsx:66-66
Timestamp: 2026-01-05T03:02:14.502Z
Learning: In the claude-code-hub project, the translations.actions.addKey field in UserKeyTableRowProps is defined as optional for backward compatibility, but all actual callers in the codebase provide the complete translations object. The field has been added to all 5 locale files (messages/{locale}/dashboard.json).

Applied to files:

  • src/app/[locale]/usage-doc/_components/quick-links.tsx
  • src/app/[locale]/usage-doc/_components/toc-nav.tsx
📚 Learning: 2026-01-07T17:05:37.171Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-07T17:05:37.171Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Place unit tests in tests/unit/, integration tests in tests/integration/, and source-adjacent tests in src/**/*.test.ts

Applied to files:

  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
📚 Learning: 2026-01-07T17:05:56.313Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-07T17:05:56.313Z
Learning: Follow the coding standards and guidelines defined in CLAUDE.md

Applied to files:

  • src/app/[locale]/usage-doc/page.tsx
🧬 Code graph analysis (1)
tests/unit/usage-doc/opencode-usage-doc.test.tsx (1)
src/app/[locale]/usage-doc/page.tsx (1)
  • UsageDocContent (138-1691)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: 🌐 API Tests
  • GitHub Check: Docker Build Test
  • GitHub Check: pr-review
  • GitHub Check: pr-description
  • GitHub Check: check-codex-status
  • GitHub Check: dev-build-deploy
🔇 Additional comments (15)
messages/en/usage.json (1)

476-562: LGTM! OpenCode 文档结构完整且内容清晰

新增的 OpenCode 使用指南结构良好,包含了完整的安装、配置、启动和常见问题板块。文档遵循了与其他 CLI 工具相同的模式,有助于用户理解。

messages/zh-TW/usage.json (1)

472-558: LGTM! 繁體中文翻譯完整準確

OpenCode 使用指南的繁體中文翻譯品質良好,術語翻譯準確,內容結構完整。

messages/zh-CN/usage.json (1)

472-558: LGTM! 简体中文翻译质量优秀

OpenCode 使用指南的简体中文翻译准确流畅,技术术语翻译恰当,内容完整清晰。

messages/ja/usage.json (1)

476-562: LGTM! 日语翻译完整准确

OpenCode 使用指南的日语翻译质量良好,使用了恰当的敬体表达,技术术语翻译准确。

messages/ru/usage.json (1)

476-562: LGTM! 俄语翻译完整准确

OpenCode 使用指南的俄语翻译质量良好,技术术语翻译恰当,内容结构完整。

src/app/[locale]/usage-doc/_components/quick-links.tsx (1)

3-3: LGTM!国际化实现正确。

正确使用 next-intluseTranslations 钩子,将硬编码的中文字符串替换为翻译键。符合项目的 i18n 规范。

Also applies to: 16-17, 30-30, 37-37

src/app/[locale]/usage-doc/_components/toc-nav.tsx (1)

3-3: LGTM!国际化与无障碍支持实现正确。

正确将 aria-label 和空状态文本国际化,符合 i18n 规范和无障碍最佳实践。

Also applies to: 28-29, 31-31, 40-40

tests/unit/usage-doc/opencode-usage-doc.test.tsx (3)

1-45: LGTM!测试辅助函数实现良好。

  • 正确使用 happy-dom 测试环境
  • renderWithIntl 辅助函数正确包装 NextIntlClientProvider 并提供清理方法
  • 正确模拟 @/i18n/routing 以避免 Next.js 运行时依赖
  • 使用 React 19 的 actcreateRoot API

47-60: LGTM!章节顺序测试覆盖全面。

测试正确验证了 OpenCode 章节在 Gemini CLI 之后、Droid 之前的位置顺序。


62-80: LGTM!配置示例内容测试覆盖全面。

测试正确验证了 opencode.json 示例包含必要的 schema、baseURL 以及所有要求的模型 ID(Claude、GPT、Gemini 系列)。

src/app/[locale]/usage-doc/page.tsx (5)

960-1039: LGTM!OpenCode 安装逻辑实现正确。

安装方法覆盖了各平台的主流方式(脚本安装、包管理器、npm),遵循了其他 CLI 安装的既有模式,i18n 使用正确。


1041-1107: LGTM!OpenCode 配置逻辑实现正确。

配置示例包含完整的 provider 设置和模型列表,正确使用 resolvedOrigin 动态生成 baseURL,翻译键使用规范。


51-56: LGTM!CLI 配置扩展合理。

  • requiresNodeJs 属性带有清晰的 JSDoc 文档说明
  • OpenCode 配置正确设置为 requiresNodeJs: false(支持二进制/脚本安装)
  • 配置结构遵循既有模式

Also applies to: 113-119


138-138: LGTM!导出 UsageDocContent 支持单元测试。

UsageDocContent 导出使其可被单元测试直接导入和渲染,是良好的可测试性实践。


1587-1598: LGTM!OpenCode 章节正确集成到主渲染流程。

OpenCode 章节按预期位于 Gemini CLI 之后、Droid 之前,遵循统一的渲染模式。

"scoop": {
"title": "Option 2: Scoop",
"description": "Install via Scoop:",
"command": "scoop bucket add extras\\nscoop install extras/opencode"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] [COMMENT-INACCURATE] Scoop command renders a literal \\n instead of a newline

Why this is a problem: This value is passed directly into <CodeBlock code={t("opencode.installation.windows.scoop.command")} /> (see src/app/[locale]/usage-doc/page.tsx:987). With \\n in JSON, users will copy/paste scoop bucket add extras\\nscoop install extras/opencode as a single command, which will fail.

Evidence: messages/en/usage.json:515 contains:
"command": "scoop bucket add extras\\nscoop install extras/opencode"

Suggested fix:

"command": "scoop bucket add extras\nscoop install extras/opencode"

"scoop": {
"title": "方式二:Scoop",
"description": "使用 Scoop 安装:",
"command": "scoop bucket add extras\\nscoop install extras/opencode"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] [COMMENT-INACCURATE] Scoop command renders a literal \\n instead of a newline

Why this is a problem: This value is passed directly into <CodeBlock code={t("opencode.installation.windows.scoop.command")} /> (see src/app/[locale]/usage-doc/page.tsx:987). With \\n in JSON, users will copy/paste scoop bucket add extras\\nscoop install extras/opencode as a single command, which will fail.

Evidence: messages/zh-CN/usage.json:511 contains:
"command": "scoop bucket add extras\\nscoop install extras/opencode"

Suggested fix:

"command": "scoop bucket add extras\nscoop install extras/opencode"

"scoop": {
"title": "方式二:Scoop",
"description": "使用 Scoop 安裝:",
"command": "scoop bucket add extras\\nscoop install extras/opencode"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] [COMMENT-INACCURATE] Scoop command renders a literal \\n instead of a newline

Why this is a problem: This value is passed directly into <CodeBlock code={t("opencode.installation.windows.scoop.command")} /> (see src/app/[locale]/usage-doc/page.tsx:987). With \\n in JSON, users will copy/paste scoop bucket add extras\\nscoop install extras/opencode as a single command, which will fail.

Evidence: messages/zh-TW/usage.json:511 contains:
"command": "scoop bucket add extras\\nscoop install extras/opencode"

Suggested fix:

"command": "scoop bucket add extras\nscoop install extras/opencode"

"scoop": {
"title": "方法2:Scoop",
"description": "Scoop でインストール:",
"command": "scoop bucket add extras\\nscoop install extras/opencode"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] [COMMENT-INACCURATE] Scoop command renders a literal \\n instead of a newline

Why this is a problem: This value is passed directly into <CodeBlock code={t("opencode.installation.windows.scoop.command")} /> (see src/app/[locale]/usage-doc/page.tsx:987). With \\n in JSON, users will copy/paste scoop bucket add extras\\nscoop install extras/opencode as a single command, which will fail.

Evidence: messages/ja/usage.json:515 contains:
"command": "scoop bucket add extras\\nscoop install extras/opencode"

Suggested fix:

"command": "scoop bucket add extras\nscoop install extras/opencode"

"scoop": {
"title": "Способ 2: Scoop",
"description": "Установка через Scoop:",
"command": "scoop bucket add extras\\nscoop install extras/opencode"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] [COMMENT-INACCURATE] Scoop command renders a literal \\n instead of a newline

Why this is a problem: This value is passed directly into <CodeBlock code={t("opencode.installation.windows.scoop.command")} /> (see src/app/[locale]/usage-doc/page.tsx:987). With \\n in JSON, users will copy/paste scoop bucket add extras\\nscoop install extras/opencode as a single command, which will fail.

Evidence: messages/ru/usage.json:515 contains:
"command": "scoop bucket add extras\\nscoop install extras/opencode"

Suggested fix:

"command": "scoop bucket add extras\nscoop install extras/opencode"

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

This PR adds an OpenCode setup section to the usage docs and updates usage-doc UI strings to use i18n. One documentation defect was found that will cause the Windows Scoop install command to be rendered/copy-pasted incorrectly in all locales.

PR Size: L

  • Lines changed: 793
  • Files changed: 9
  • Split suggestion: separate i18n message additions (messages/*/usage.json), usage-doc UI changes (src/app/[locale]/usage-doc/*), and tests (tests/unit/usage-doc/*) into 2–3 PRs.

Issues Found

Category Critical High Medium Low
Logic/Bugs 0 0 0 0
Security 0 0 0 0
Error Handling 0 0 0 0
Types 0 0 0 0
Comments/Docs 0 1 0 0
Tests 0 0 0 0
Simplification 0 0 0 0

Critical Issues (Must Fix)

  • None

High Priority Issues (Should Fix)

  • [HIGH] [COMMENT-INACCURATE] Windows Scoop command uses \\n instead of a newline in opencode.installation.windows.scoop.command (confidence 85).

Review Coverage

  • Logic and correctness
  • Security (OWASP Top 10)
  • Error handling
  • Type safety
  • Documentation accuracy
  • Test coverage
  • Code clarity

Automated review by Codex AI

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Reviewed PR #582 (docs: add OpenCode setup guide), computed size L (793 lines, 9 files), and applied label size/L.
  • Left 5 inline comments for a [HIGH] [COMMENT-INACCURATE] defect: opencode.installation.windows.scoop.command is stored as "extras\\nscoop ..." (literal \n) so the rendered <CodeBlock> will be copy/pasted as one broken command (messages/en/usage.json:515, messages/zh-CN/usage.json:511, messages/zh-TW/usage.json:511, messages/ja/usage.json:515, messages/ru/usage.json:515). Suggested fix is to use a real newline escape (\n) in the JSON string.
  • Submitted the required summary review via gh pr review --comment.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

This PR adds comprehensive OpenCode CLI setup documentation with full i18n support for all 5 supported languages. The implementation follows existing patterns for CLI documentation and properly integrates with the codebase.

PR Size: L

  • Lines changed: 793 (768 additions + 25 deletions)
  • Files changed: 9

Issues Found

Category Critical High Medium Low
Logic/Bugs 0 0 0 0
Security 0 0 0 0
Error Handling 0 0 0 0
Types 0 0 0 0
Comments/Docs 0 0 0 0
Tests 0 0 0 0
Simplification 0 0 0 0

Review Notes

Verified correct implementation:

  • requiresNodeJs property properly added to CLIConfig interface and correctly used to conditionally render Node.js setup section
  • OpenCode section correctly positioned after Gemini CLI and before Droid
  • Environment variable check in troubleshooting section correctly updated to check for CCH_API_KEY for both codex and opencode
  • UsageDocContent export added to support new unit tests
  • All 5 i18n translation files (zh-CN, zh-TW, en, ja, ru) include complete OpenCode section translations
  • Unit tests cover ordering verification, configuration content validation, and i18n key presence

Code quality observations:

  • The i18n fix for hardcoded Chinese text in quick-links.tsx and toc-nav.tsx is a good cleanup
  • Emoji removal from h2 titles aligns with CLAUDE.md "No Emoji in Code" rule
  • Test file follows project conventions with proper vitest environment setup and mocking

Review Coverage

  • Logic and correctness - Clean
  • Security (OWASP Top 10) - Clean
  • Error handling - N/A (documentation rendering)
  • Type safety - Clean
  • Documentation accuracy - Clean
  • Test coverage - Adequate (new tests added)
  • Code clarity - Good

Automated review by Claude AI

@github-actions
Copy link
Contributor

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/app/[locale]/usage-doc/page.tsx (2)

1328-1467: OpenCode 的“更新命令”与安装方式不匹配;建议为 opencode 单独提供更新指引。

当前逻辑只要 cli.packageName 存在就默认 npm install -g ${cli.packageName}(Line 1459),这对 OpenCode(同时提供 script/homebrew 安装,Line 1019/1028)不一定成立,容易造成文档误导。建议像 codex/gemini 一样,为 opencode 增加专用 t("opencode.commonIssues.updateCommand")(或按安装方式分别给出)。


72-131: 修正 OpenCode 配置中的 Node.js 依赖标志

opencode 配置的 requiresNodeJs: false(Line 118)与实际安装要求不符。OpenCode CLI 官方要求 Node.js 18 或更高版本,且通过 npm install -g opencode-ai 安装,因此必须设置 requiresNodeJs: true

建议改为:

opencode: {
  title: t("opencode.title"),
  id: "opencode",
  cliName: "opencode",
  packageName: "opencode-ai",
  requiresNodeJs: true,  // 修改此行
  ...
}
🤖 Fix all issues with AI agents
In @src/app/[locale]/usage-doc/page.tsx:
- Around line 1044-1109: In renderOpenCodeConfiguration, fix the Windows path
and the config JSON: change configPath for windows from
"%USERPROFILE%\\.config\\opencode\\opencode.json" to use PowerShell syntax
"$env:USERPROFILE\\.config\\opencode\\opencode.json" (CodeBlock language stays
"powershell"), add a top-level "model" field to opencodeConfigJson with a
default like "cch/gpt-5.2" (so default model points to the provider prefix +
model-id), and remove non-standard fields "theme" and "autoupdate" from
opencodeConfigJson so the JSON matches the official OpenCode spec; keep using
resolvedOrigin for provider.options.baseURL and preserve the existing models map
and t.raw replacement logic.
🧹 Nitpick comments (3)
src/app/[locale]/usage-doc/page.tsx (3)

46-64: requiresNodeJs?: boolean 建模方向 OK,但建议避免“缺省即不渲染”的隐式行为。

目前 renderPlatformGuidecli.requiresNodeJs && ... 做 gating(Line 1486),如果未来新增 CLI 忘了设置该字段,会静默漏掉环境准备步骤。考虑将其改为必填(或在 getCLIConfigs 里统一显式赋值),降低回归风险。


960-1039: OpenCode 安装命令存在硬编码与复用问题;且安装命令需要与官方文档保持一致。

  • npm install -g opencode-ai 在多个分支硬编码(Line 996、1035),按仓库规范建议也走 i18n key,便于多语言一致维护。
  • Windows 分支与 macOS/Linux 分支的 npm 安装命令完全相同,建议抽成一个常量,避免未来改动漏改。
建议改动(抽出 npm 安装命令并走 i18n key)
   const renderOpenCodeInstallation = (os: OS) => {
+    const npmInstallCommand = t("opencode.installation.npm.command");
     if (os === "windows") {
       return (
         <div className="space-y-4">
@@
           <div className="space-y-3">
             <h5 className="font-semibold text-foreground">
               {t("opencode.installation.npm.title")}
             </h5>
             <p>{t("opencode.installation.npm.description")}</p>
-            <CodeBlock language="powershell" code={`npm install -g opencode-ai`} />
+            <CodeBlock language="powershell" code={npmInstallCommand} />
           </div>
         </div>
       );
     }
@@
       <div className="space-y-3">
         <h5 className="font-semibold text-foreground">{t("opencode.installation.npm.title")}</h5>
         <p>{t("opencode.installation.npm.description")}</p>
-        <CodeBlock language="bash" code={`npm install -g opencode-ai`} />
+        <CodeBlock language="bash" code={npmInstallCommand} />
       </div>
     </div>
   );
 };

1279-1323: titleKey/descKey/initKey 的多层三元表达式可读性偏低,建议用映射表替代。

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

📥 Commits

Reviewing files that changed from the base of the PR and between 98f04d2 and ec14780.

📒 Files selected for processing (7)
  • messages/en/usage.json
  • messages/ja/usage.json
  • messages/ru/usage.json
  • messages/zh-CN/usage.json
  • messages/zh-TW/usage.json
  • src/app/[locale]/usage-doc/page.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

No emoji characters in any code, comments, or string literals

Files:

  • src/app/[locale]/usage-doc/page.tsx
**/*.{ts,tsx,jsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,jsx,js}: All user-facing strings must use i18n (5 languages supported: zh-CN, en, ja, ko, de). Never hardcode display text
Use path alias @/ to map to ./src/
Use Biome for code formatting with configuration: double quotes, trailing commas, 2-space indent, 100 character line width
Prefer named exports over default exports
Use next-intl for internationalization
Use Next.js 16 App Router with Hono for API routes

Files:

  • src/app/[locale]/usage-doc/page.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use React 19, shadcn/ui, Tailwind CSS, and Recharts for the UI layer

Files:

  • src/app/[locale]/usage-doc/page.tsx
🧠 Learnings (1)
📚 Learning: 2026-01-07T17:05:56.313Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-07T17:05:56.313Z
Learning: Follow the coding standards and guidelines defined in CLAUDE.md

Applied to files:

  • src/app/[locale]/usage-doc/page.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 🌐 API Tests
  • GitHub Check: Docker Build Test
  • GitHub Check: dev-build-deploy
🔇 Additional comments (8)
messages/ja/usage.json (1)

476-562: 无重复的顶层 JSON 键。文件中仅存在一个 opencode 键,JSON 结构有效。此处无需修改。

Likely an incorrect or invalid review comment.

messages/en/usage.json (1)

476-562: 原始审查意见中关于重复 opencode 顶层键的指控不成立。验证结果显示:

  • JSON 文件格式有效
  • opencode 键仅在文件中出现 1 次
  • 文件中不存在重复的顶层键

无需进行任何修改。

Likely an incorrect or invalid review comment.

messages/zh-CN/usage.json (1)

472-558: 审核意见撤回:不存在重复的 JSON 键问题

经验证,messages/zh-CN/usage.json 文件中不存在重复的 opencode 键。验证结果表明:

  • 顶层仅存在一个 opencode
  • JSON 格式完全有效
  • 文件结构正确无误

原审核意见基于错误的信息,此问题不存在。

Likely an incorrect or invalid review comment.

messages/zh-TW/usage.json (1)

472-558: 本次审查涉及的关键问题已得到验证。经过对 messages/zh-TW/usage.json 文件的 JSON 结构检查,确认该文件中不存在重复的顶层 opencode 键。验证结果表明:

  • opencode 键在文件中仅出现 1 次
  • 文件顶层包含 14 个唯一的键,无任何重复
  • JSON 结构完全有效,无语法错误

原审查意见基于不正确的前提(AI 摘要错误地指出存在重复块)。此文件中不存在所述的严重重复键问题。

Likely an incorrect or invalid review comment.

messages/ru/usage.json (1)

476-562: 无重复的顶层 JSON 键问题。

验证显示 messages/ru/usage.json 和所有其他语言环境文件(ja、en、zh-TW、zh-CN)都包含有效的 JSON,每个文件中 opencode 键仅出现一次。所有 5 个文件的结构一致,各有 14 个顶层键。不存在重复键或数据完整性问题。

Likely an incorrect or invalid review comment.

src/app/[locale]/usage-doc/page.tsx (3)

138-142: 导出 UsageDocContent 便于测试/复用,OK。


1472-1546: requiresNodeJs gating 环境准备思路 OK,但与 OpenCode 的安装选项需要一致(见前述)。


1592-1604: OpenCode 章节插入位置(Gemini 之后、Droid 之前)符合 PR 目标。

Comment on lines 1044 to 1109
const renderOpenCodeConfiguration = (os: OS) => {
const configPath =
os === "windows"
? "%USERPROFILE%\\.config\\opencode\\opencode.json"
: "~/.config/opencode/opencode.json";

const opencodeConfigJson = JSON.stringify(
{
$schema: "https://opencode.ai/config.json",
theme: "opencode",
autoupdate: false,
provider: {
cch: {
npm: "@ai-sdk/openai-compatible",
name: "Claude Code Hub (cch)",
options: {
baseURL: `${resolvedOrigin}/v1`,
apiKey: "{env:CCH_API_KEY}",
},
models: {
"claude-haiku-4-5-20251001": { name: "Claude Haiku 4.5" },
"claude-sonnet-4-5-20250929": { name: "Claude Sonnet 4.5" },
"claude-opus-4-5-20251101": { name: "Claude Opus 4.5" },
"gpt-5.2": { name: "GPT-5.2" },
"gemini-3-pro-preview": { name: "Gemini 3 Pro Preview" },
"gemini-3-flash-preview": { name: "Gemini 3 Flash Preview" },
},
},
},
},
null,
2
);

return (
<div className="space-y-4">
<h4 className={headingClasses.h4}>{t("opencode.configuration.configFile.title")}</h4>

<div className="space-y-3">
<p>{t("opencode.configuration.configFile.path")}</p>
<CodeBlock language={os === "windows" ? "powershell" : "bash"} code={configPath} />
<p>{t("opencode.configuration.configFile.instruction")}</p>
<CodeBlock language="json" code={opencodeConfigJson} />

<blockquote className="space-y-2 rounded-lg border-l-2 border-primary/50 bg-muted/40 px-4 py-3">
<p className="font-semibold text-foreground">
{t("opencode.configuration.configFile.important")}
</p>
<ul className="list-disc space-y-2 pl-4">
{(t.raw("opencode.configuration.configFile.importantPoints") as string[]).map(
(point: string, i: number) => (
<li key={i}>{point.replace("${resolvedOrigin}", resolvedOrigin)}</li>
)
)}
</ul>
</blockquote>
</div>

<h4 className={headingClasses.h4}>{t("opencode.configuration.modelSelection.title")}</h4>
<div className="space-y-3">
<p>{t("opencode.configuration.modelSelection.description")}</p>
<CodeBlock language="text" code={t("opencode.configuration.modelSelection.command")} />
</div>
</div>
);
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

OpenCode opencode.ai official configuration schema opencode.json provider models

💡 Result:

Short summary of the official opencode.json schema (provider → models) and key fields:

  • Schema root: "$schema": "https://opencode.ai/config.json". [1]

  • Top-level keys used for providers/models: provider, model, small_model. [3][2]

  • provider map: key = provider_id (any string). Provider object commonly contains:

    • npm — package to use (e.g. "@ai-sdk/openai-compatible"). [1][3]
    • name — display name. [1]
    • options — provider-level options (baseURL, apiKey, timeout, setCacheKey, etc.). [1][3]
    • models — map of model_id → model configuration. [1][2]
  • model entry fields (per model_id):

    • name — display name for the model.
    • limit — optional limits (e.g. context, output). [1]
    • options — model-specific options (e.g. provider ordering / allow_fallbacks). [1]
    • variants — named variants (reasoningEffort, textVerbosity, disabled, etc.). [2]
  • How to reference a model: "provider_id/model_id" (e.g. "anthropic/claude-sonnet-4-5"). Set default with "model" key. [2][3]

Minimal example (based on docs):

{
"$schema": "https://opencode.ai/config.json",
"provider": {
"myprovider": {
"npm": "@ai-sdk/openai-compatible",
"name": "My AI Provider",
"options": { "baseURL": "https://api.myprovider.com/v1" },
"models": {
"my-model": {
"name": "My Model Display Name",
"limit": { "context": 131072, "output": 65536 },
"variants": { "fast": { "disabled": true } }
}
}
}
},
"model": "myprovider/my-model"
}

Sources: OpenCode docs — Providers, Models, Config. [1][2][3]


🏁 Script executed:

# Search for any OpenCode-related configuration or references in the repository
rg "opencode" --type ts --type tsx -i --max-count 20

Repository: ding113/claude-code-hub

Length of output: 94


🏁 Script executed:

# Check if there are any tests or documentation about the OpenCode configuration
fd -e json -e ts -e tsx | xargs rg "provider|models|cch" -l | head -20

Repository: ding113/claude-code-hub

Length of output: 913


🏁 Script executed:

# Look at the complete context of the configuration in the page file
grep -n "resolvedOrigin\|provider\|models\|opencode" src/app/[locale]/usage-doc/page.tsx | head -30

Repository: ding113/claude-code-hub

Length of output: 1878


🏁 Script executed:

# Check the OpenCode test file to understand expected configuration structure
cat -n tests/unit/usage-doc/opencode-usage-doc.test.tsx

Repository: ding113/claude-code-hub

Length of output: 3897


🏁 Script executed:

# Read the complete renderOpenCodeConfiguration function from the page
sed -n '1044,1109p' src/app/[locale]/usage-doc/page.tsx | cat -n

Repository: ding113/claude-code-hub

Length of output: 3100


🏁 Script executed:

# Check for any schema validation or OpenCode config references
rg "opencode.json|provider|models" -A 3 -B 3 src/app/[locale]/usage-doc/page.tsx | head -100

Repository: ding113/claude-code-hub

Length of output: 2243


Windows 的 OpenCode 配置路径对 PowerShell 不准确;配置 JSON 缺少默认模型指定。

  • 路径语法问题:Line 1047 中 configPath 使用了 %USERPROFILE%(cmd 风格),但 Line 1084 将其显示为 powershell 代码块。PowerShell 应使用 $env:USERPROFILE 替代。
  • 缺少默认模型指定:当前 opencodeConfigJson 结构(Line 1050-1076)仅包含 provider 对象,但 OpenCode 官方配置规范要求在顶级添加 model 字段来指定默认模型(格式:"model": "cch/model-id")。
  • 非标准配置字段:配置包含 themeautoupdate 字段,这些字段在 OpenCode 官方文档中未被记录。
建议改动
   const renderOpenCodeConfiguration = (os: OS) => {
     const configPath =
       os === "windows"
-        ? "%USERPROFILE%\\.config\\opencode\\opencode.json"
+        ? "$env:USERPROFILE\\.config\\opencode\\opencode.json"
         : "~/.config/opencode/opencode.json";

     const opencodeConfigJson = JSON.stringify(
       {
         $schema: "https://opencode.ai/config.json",
-        theme: "opencode",
-        autoupdate: false,
         provider: {
           cch: {
             npm: "@ai-sdk/openai-compatible",
             name: "Claude Code Hub (cch)",
             options: {
               baseURL: `${resolvedOrigin}/v1`,
               apiKey: "{env:CCH_API_KEY}",
             },
             models: {
               "claude-haiku-4-5-20251001": { name: "Claude Haiku 4.5" },
               "claude-sonnet-4-5-20250929": { name: "Claude Sonnet 4.5" },
               "claude-opus-4-5-20251101": { name: "Claude Opus 4.5" },
               "gpt-5.2": { name: "GPT-5.2" },
               "gemini-3-pro-preview": { name: "Gemini 3 Pro Preview" },
               "gemini-3-flash-preview": { name: "Gemini 3 Flash Preview" },
             },
           },
         },
+        model: "cch/claude-opus-4-5-20251101",
       },
       null,
       2
     );
🤖 Prompt for AI Agents
In @src/app/[locale]/usage-doc/page.tsx around lines 1044 - 1109, In
renderOpenCodeConfiguration, fix the Windows path and the config JSON: change
configPath for windows from "%USERPROFILE%\\.config\\opencode\\opencode.json" to
use PowerShell syntax "$env:USERPROFILE\\.config\\opencode\\opencode.json"
(CodeBlock language stays "powershell"), add a top-level "model" field to
opencodeConfigJson with a default like "cch/gpt-5.2" (so default model points to
the provider prefix + model-id), and remove non-standard fields "theme" and
"autoupdate" from opencodeConfigJson so the JSON matches the official OpenCode
spec; keep using resolvedOrigin for provider.options.baseURL and preserve the
existing models map and t.raw replacement logic.

@github-actions
Copy link
Contributor

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @messages/ru/usage.json:
- Around line 476-562: The installation entries are missing their command
strings; add a "command" field to installation.script (official install script
command), installation.npm (global npm install command), and
installation.macos.homebrew (Homebrew install command) inside the "opencode"
object so they match the existing pattern used by installation.windows.choco and
installation.windows.scoop; locate and update the keys installation.script,
installation.npm, and installation.macos.homebrew to include the appropriate
shell command texts.

In @messages/zh-CN/usage.json:
- Around line 472-558: The install command strings for macOS Homebrew, script,
and npm are hardcoded in the usage doc component (page.tsx) instead of being
pulled from i18n; add command fields to the JSON under
opencode.installation.macos.homebrew.command,
opencode.installation.script.command, and opencode.installation.npm.command,
then update the usage doc rendering code in page.tsx to read those keys (e.g.,
opencode.installation.script, opencode.installation.npm,
opencode.installation.macos.homebrew) from the i18n bundle rather than using
embedded literals so all platforms' install commands are consistently localized.

In @messages/zh-TW/usage.json:
- Around line 472-558: The installation commands are inconsistently sourced:
only opencode.installation.windows.choco.command and .scoop.command exist in the
JSON while macOS (homebrew), linux, script and npm commands are hardcoded in the
React UI; update the JSON by adding a "command" field under
opencode.installation.homebrew, opencode.installation.linux,
opencode.installation.script and opencode.installation.npm (matching the
existing windows.*.command shape) and refactor the React component to read these
commands from the JSON keys (opencode.installation.*.command) instead of using
the hardcoded strings so all install commands are maintained in one place.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

📥 Commits

Reviewing files that changed from the base of the PR and between ec14780 and 5e173dc.

📒 Files selected for processing (5)
  • messages/en/usage.json
  • messages/ja/usage.json
  • messages/ru/usage.json
  • messages/zh-CN/usage.json
  • messages/zh-TW/usage.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • messages/ja/usage.json
  • messages/en/usage.json
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-01-10T06:20:04.478Z
Learnt from: NieiR
Repo: ding113/claude-code-hub PR: 573
File: src/actions/model-prices.ts:275-335
Timestamp: 2026-01-10T06:20:04.478Z
Learning: In the `ding113/claude-code-hub` repository, Server Actions (files under `src/actions/*.ts`) currently return hardcoded Chinese error messages directly. This is a codebase-wide architectural decision that applies to all action files (e.g., model-prices.ts, users.ts, system-config.ts). Changing this pattern requires a coordinated i18n refactor across all Server Actions, which should be handled as a separate unified task rather than piecemeal changes in individual PRs.

Applied to files:

  • messages/zh-CN/usage.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 🌐 API Tests
  • GitHub Check: Docker Build Test
  • GitHub Check: dev-build-deploy

Comment on lines 476 to 562
"opencode": {
"title": "Руководство по OpenCode",
"description": "OpenCode — это CLI + TUI агент для программирования в терминале, также есть интеграции для IDE. Вы можете настроить OpenCode на cch как единый вход для доступа к моделям Claude, GPT и Gemini.",

"installation": {
"title": "Установка",

"macos": {
"description": "В macOS установите OpenCode одним из следующих способов:",
"homebrew": {
"title": "Способ 2: Homebrew",
"description": "Установка через Homebrew:"
}
},

"linux": {
"description": "В Linux установите OpenCode одним из следующих способов:"
},

"script": {
"title": "Способ 1: Официальный install-скрипт",
"description": "Выполните команду для установки последней версии:"
},

"npm": {
"title": "Способ 3: npm",
"description": "Глобальная установка через npm:"
},

"windows": {
"description": "В Windows рекомендуем использовать пакетный менеджер (Chocolatey/Scoop), либо npm:",
"choco": {
"title": "Способ 1: Chocolatey",
"description": "Установка через Chocolatey:",
"command": "choco install opencode"
},
"scoop": {
"title": "Способ 2: Scoop",
"description": "Установка через Scoop:",
"command": "scoop bucket add extras\nscoop install extras/opencode"
}
}
},

"configuration": {
"title": "Подключение к cch",

"configFile": {
"title": "Настройка opencode.json",
"path": "Путь к конфигурационному файлу:",
"instruction": "Отредактируйте файл и добавьте следующий контент (один файл покрывает все модели):",

"important": "Важно",
"importantPoints": [
"Создайте API key в панели cch и задайте переменную окружения CCH_API_KEY",
"baseURL использует ${resolvedOrigin}/v1 (базовый URL cch v1 API)",
"ID модели можно указывать как имена моделей Claude / GPT / Gemini — cch маршрутизирует автоматически"
]
},

"modelSelection": {
"title": "Выбор модели",
"description": "После запуска OpenCode в TUI выполните команду для просмотра/выбора моделей:",
"command": "/models"
}
},

"startup": {
"title": "Запуск opencode",
"description": "В каталоге проекта выполните:",
"initNote": "При первом запуске opencode загрузит конфигурацию и создаст сессию."
},

"commonIssues": {
"title": "Типичные проблемы",

"commandNotFound": "1. Команда не найдена",
"commandNotFoundWindows": [
"Если установили через npm, убедитесь, что глобальный npm bin добавлен в PATH",
"Откройте новый терминал и повторите"
],
"commandNotFoundUnix": "Проверьте путь установки и добавьте его в PATH (например, ~/.local/bin или глобальный npm bin)",

"connectionFailed": "2. Сбой подключения API",
"updateCli": "3. Обновление opencode"
}
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

python - <<'PY'
import json, pathlib

def no_dupe_object_pairs_hook(pairs):
    obj = {}
    for k, v in pairs:
        if k in obj:
            raise ValueError(f"duplicate key: {k!r}")
        obj[k] = v
    return obj

p = pathlib.Path("messages/ru/usage.json")
s = p.read_text(encoding="utf-8")
json.loads(s, object_pairs_hook=no_dupe_object_pairs_hook)
print("✓ JSON 格式有效,无重复键")
PY

# 检查是否存在 opencode 渲染依赖
echo "=== 检查 src 中 opencode 的使用情况 ==="
rg -n "opencode" src --type ts --type tsx --type js --type jsx 2>/dev/null || echo "未找到 src 中的 opencode 引用"

# 验证 installation 块中 command 字段的使用
echo "=== 检查 installation 块结构 ==="
python - <<'PY2'
import json
import pathlib

p = pathlib.Path("messages/ru/usage.json")
data = json.loads(p.read_text(encoding="utf-8"))

if "opencode" in data:
    inst = data["opencode"].get("installation", {})
    print(f"installation 块中的子键: {list(inst.keys())}")
    
    # 检查每个子块是否有 command 字段
    for key, val in inst.items():
        if isinstance(val, dict):
            has_command = "command" in val
            print(f"  {key}: command={has_command}, keys={list(val.keys())}")
PY2

Repository: ding113/claude-code-hub

Length of output: 153


🏁 Script executed:

#!/bin/bash

# 检查文件是否存在和大小
echo "=== 检查文件 ==="
ls -lh messages/ru/usage.json 2>/dev/null || echo "文件未找到"

# 用 jq 验证 JSON 有效性并检查 opencode 块
echo "=== 验证 JSON 结构 ==="
jq '.opencode | keys' messages/ru/usage.json 2>/dev/null || echo "jq 解析失败"

# 检查 installation 块中的 command 字段
echo "=== 检查 installation 块中的 command 字段 ==="
jq '.opencode.installation | to_entries[] | select(.value | type == "object") | {key: .key, has_command: (.value | has("command")), has_description: (.value | has("description")), has_title: (.value | has("title"))}' messages/ru/usage.json 2>/dev/null

# 检查是否存在重复的 opencode 顶级键
echo "=== 检查顶级 opencode 键出现次数 ==="
grep -c '"opencode"' messages/ru/usage.json || echo "无法统计"

Repository: ding113/claude-code-hub

Length of output: 806


🏁 Script executed:

#!/bin/bash

# 检查所有包含 command 字段的对象及其路径
echo "=== 深层检查所有 command 字段 ==="
jq '.opencode.installation | walk(if type == "object" and has("command") then . else empty end)' messages/ru/usage.json 2>/dev/null | head -20

# 详细列出 script, npm, homebrew, windows.choco, windows.scoop 的完整结构
echo "=== 检查 script 块 ==="
jq '.opencode.installation.script' messages/ru/usage.json

echo "=== 检查 npm 块 ==="
jq '.opencode.installation.npm' messages/ru/usage.json

echo "=== 检查 homebrew 块 ==="
jq '.opencode.installation.macos.homebrew' messages/ru/usage.json

echo "=== 检查 windows 块 ==="
jq '.opencode.installation.windows' messages/ru/usage.json

Repository: ding113/claude-code-hub

Length of output: 879


安装块中 script、npm、homebrew 缺少 command 字段,需要补齐。

验证发现 messages/ru/usage.json 的 opencode 块无重复键(✓),但以下安装方法缺少实际的安装命令:

  • installation.script:应包含官方安装脚本的命令
  • installation.npm:应包含全局 npm 安装的命令
  • installation.macos.homebrew:应包含 Homebrew 安装的命令

相比之下,installation.windows.chocoinstallation.windows.scoop 都已正确包含 command 字段。为保持一致性和完整性,需要为上述三个块添加相应的 command 字段。

🤖 Prompt for AI Agents
In @messages/ru/usage.json around lines 476 - 562, The installation entries are
missing their command strings; add a "command" field to installation.script
(official install script command), installation.npm (global npm install
command), and installation.macos.homebrew (Homebrew install command) inside the
"opencode" object so they match the existing pattern used by
installation.windows.choco and installation.windows.scoop; locate and update the
keys installation.script, installation.npm, and installation.macos.homebrew to
include the appropriate shell command texts.

Comment on lines 472 to 558
"opencode": {
"title": "OpenCode 使用指南",
"description": "OpenCode 是一款在终端中运行的 CLI + TUI AI 编程代理工具,也提供 IDE 插件集成。你可以将 OpenCode 指向 cch 作为统一入口来接入 Claude、GPT 与 Gemini 等模型。",

"installation": {
"title": "安装",

"macos": {
"description": "在 macOS 上可以选择以下任一种方式安装 OpenCode:",
"homebrew": {
"title": "方式二:Homebrew",
"description": "也可以使用 Homebrew 安装:"
}
},

"linux": {
"description": "在 Linux 上可以选择以下任一种方式安装 OpenCode:"
},

"script": {
"title": "方式一:官方安装脚本",
"description": "执行以下命令安装最新版:"
},

"npm": {
"title": "方式三:npm",
"description": "也可以通过 npm 全局安装:"
},

"windows": {
"description": "Windows 推荐使用包管理器(Chocolatey/Scoop),也可以使用 npm:",
"choco": {
"title": "方式一:Chocolatey",
"description": "使用 Chocolatey 安装:",
"command": "choco install opencode"
},
"scoop": {
"title": "方式二:Scoop",
"description": "使用 Scoop 安装:",
"command": "scoop bucket add extras\nscoop install extras/opencode"
}
}
},

"configuration": {
"title": "连接 cch 服务",

"configFile": {
"title": "配置 opencode.json",
"path": "配置文件路径:",
"instruction": "编辑配置文件,写入以下内容(只需一份配置文件即可覆盖全部模型):",

"important": "重要说明",
"importantPoints": [
"请先在 cch 后台创建 API Key,并设置环境变量 CCH_API_KEY",
"baseURL 使用 ${resolvedOrigin}/v1(cch v1 API 地址)",
"模型 ID 直接填写 claude / gpt / gemini 的模型名即可,cch 会自动路由到对应上游"
]
},

"modelSelection": {
"title": "选择模型",
"description": "启动 OpenCode 后,在 TUI 中输入以下命令查看/选择模型:",
"command": "/models"
}
},

"startup": {
"title": "启动 opencode",
"description": "在项目目录下运行:",
"initNote": "首次启动时,opencode 会加载配置并创建会话。"
},

"commonIssues": {
"title": "常见问题",

"commandNotFound": "1. 命令未找到",
"commandNotFoundWindows": [
"如果使用 npm 安装,请确保 npm 全局路径已添加到系统 PATH",
"重新打开终端窗口后再试"
],
"commandNotFoundUnix": "检查安装路径并添加到 PATH(例如 ~/.local/bin 或 npm 全局目录)",

"connectionFailed": "2. API 连接失败",
"updateCli": "3. 更新 opencode"
}
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

python - <<'PY'
import json, pathlib

def no_dupe_object_pairs_hook(pairs):
    obj = {}
    for k, v in pairs:
        if k in obj:
            raise ValueError(f"duplicate key: {k!r}")
        obj[k] = v
    return obj

p = pathlib.Path("messages/zh-CN/usage.json")
s = p.read_text(encoding="utf-8")
json.loads(s, object_pairs_hook=no_dupe_object_pairs_hook)
print("OK: no duplicate keys detected in messages/zh-CN/usage.json")
PY

rg -n --hidden --glob '!**/node_modules/**' -S "usage\.opencode|opencode\.(installation|configuration|startup|commonIssues)" src --max-count 50

Repository: ding113/claude-code-hub

Length of output: 153


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1. 检查 JSON 重复 key
echo "=== 检查 JSON 完整性 ==="
python - <<'PY'
import json, pathlib

def no_dupe_object_pairs_hook(pairs):
    obj = {}
    for k, v in pairs:
        if k in obj:
            raise ValueError(f"duplicate key: {k!r}")
        obj[k] = v
    return obj

p = pathlib.Path("messages/zh-CN/usage.json")
s = p.read_text(encoding="utf-8")
data = json.loads(s, object_pairs_hook=no_dupe_object_pairs_hook)
print("✓ JSON 无重复 key")
print(f"✓ 顶级 key: {list(data.keys())}")
if 'opencode' in data:
    print(f"✓ opencode 定义存在,子 key: {list(data['opencode'].keys())}")
PY

# 2. 检查是否有多个 JSON 文件包含 opencode
echo ""
echo "=== 搜索包含 opencode 的 JSON 文件 ==="
fd -e json -x grep -l '"opencode"' {} \; 2>/dev/null | head -20

# 3. 检查 src 目录中对 opencode 的引用(限制搜索范围)
echo ""
echo "=== 检查 src 中对 installation/configuration 的引用 ==="
fd -type f -path "*/src/*" \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" \) | head -20

Repository: ding113/claude-code-hub

Length of output: 569


🏁 Script executed:

#!/bin/bash

# 1. 检查 installation 结构
echo "=== installation 结构检查 ==="
python - <<'PY'
import json, pathlib

p = pathlib.Path("messages/zh-CN/usage.json")
data = json.loads(p.read_text(encoding="utf-8"))
inst = data.get('opencode', {}).get('installation', {})
print("installation 的所有 key:")
for key in inst.keys():
    print(f"  - {key}")
    if isinstance(inst[key], dict):
        subkeys = inst[key].keys()
        print(f"      子 key: {list(subkeys)}")
        if 'command' in inst[key]:
            print(f"      有 command 字段: YES")
        else:
            print(f"      有 command 字段: NO")
PY

echo ""
echo "=== 搜索 src 中对 installation/command 的使用 ==="
find src -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" \) 2>/dev/null | wc -l
echo "源文件数量(预估),逐一检查..."
find src -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" \) -print0 2>/dev/null | xargs -0 grep -l "installation\|command.*opencode\|opencode.*installation" 2>/dev/null | head -10

Repository: ding113/claude-code-hub

Length of output: 585


🏁 Script executed:

#!/bin/bash

echo "=== page.tsx 中的 installation 相关代码 ==="
grep -n -A 20 -B 5 "installation\|script.*command\|npm.*command" src/app/[locale]/usage-doc/page.tsx | head -100

echo ""
echo "=== 搜索硬编码的命令字符串 ==="
grep -n "choco install\|scoop install\|scoop bucket\|npm install.*opencode" src/app/[locale]/usage-doc/page.tsx

Repository: ding113/claude-code-hub

Length of output: 4564


🏁 Script executed:

#!/bin/bash

echo "=== 检查 996 和 1035 周围的代码上下文 ==="
sed -n '990,1000p' src/app/[locale]/usage-doc/page.tsx
echo ""
sed -n '1030,1040p' src/app/[locale]/usage-doc/page.tsx

Repository: ding113/claude-code-hub

Length of output: 789


🏁 Script executed:

#!/bin/bash

echo "=== 搜索 opencode.installation.script 和 homebrew 相关的代码 ==="
grep -n -B 5 -A 10 "opencode.installation.script\|opencode.installation.macos.homebrew" src/app/[locale]/usage-doc/page.tsx | head -60

Repository: ding113/claude-code-hub

Length of output: 1325


统一安装命令的来源:i18n 配置与代码硬编码不一致

验证确认:

  • ✓ 无重复 opencode 顶级键,JSON 结构完整
  • ✗ 发现安装命令来源混合:
    • scriptnpmmacos.homebrew 的命令硬编码在 src/app/[locale]/usage-doc/page.tsx 中(line 1019, 1028, 1035)
    • windows.chocowindows.scoop 的命令来自 JSON i18n 配置

建议:为保持一致性和可维护性,应将 scriptnpmmacos.homebrew 的命令字段添加到 i18n JSON 中,而非硬编码在代码中。这样所有平台的安装命令都统一通过 i18n 管理,便于后续更新。

🤖 Prompt for AI Agents
In @messages/zh-CN/usage.json around lines 472 - 558, The install command
strings for macOS Homebrew, script, and npm are hardcoded in the usage doc
component (page.tsx) instead of being pulled from i18n; add command fields to
the JSON under opencode.installation.macos.homebrew.command,
opencode.installation.script.command, and opencode.installation.npm.command,
then update the usage doc rendering code in page.tsx to read those keys (e.g.,
opencode.installation.script, opencode.installation.npm,
opencode.installation.macos.homebrew) from the i18n bundle rather than using
embedded literals so all platforms' install commands are consistently localized.

Comment on lines 472 to 558
"opencode": {
"title": "OpenCode 使用指南",
"description": "OpenCode 是一款在終端中運行的 CLI + TUI AI 編程代理工具,也提供 IDE 插件集成。你可以將 OpenCode 指向 cch 作為統一入口接入 Claude、GPT 與 Gemini 等模型。",

"installation": {
"title": "安裝",

"macos": {
"description": "在 macOS 上可以選擇以下任一方式安裝 OpenCode:",
"homebrew": {
"title": "方式二:Homebrew",
"description": "也可以使用 Homebrew 安裝:"
}
},

"linux": {
"description": "在 Linux 上可以選擇以下任一方式安裝 OpenCode:"
},

"script": {
"title": "方式一:官方安裝腳本",
"description": "執行以下命令安裝最新版:"
},

"npm": {
"title": "方式三:npm",
"description": "也可以通過 npm 全局安裝:"
},

"windows": {
"description": "Windows 推薦使用包管理器(Chocolatey/Scoop),也可以使用 npm:",
"choco": {
"title": "方式一:Chocolatey",
"description": "使用 Chocolatey 安裝:",
"command": "choco install opencode"
},
"scoop": {
"title": "方式二:Scoop",
"description": "使用 Scoop 安裝:",
"command": "scoop bucket add extras\nscoop install extras/opencode"
}
}
},

"configuration": {
"title": "連接 cch 服務",

"configFile": {
"title": "配置 opencode.json",
"path": "配置文件路徑:",
"instruction": "編輯配置文件,寫入以下內容(只需一份配置文件即可覆蓋全部模型):",

"important": "重要說明",
"importantPoints": [
"請先在 cch 後台創建 API Key,並設置環境變量 CCH_API_KEY",
"baseURL 使用 ${resolvedOrigin}/v1(cch v1 API 地址)",
"模型 ID 直接填 claude / gpt / gemini 的模型名,cch 會自動路由到對應上游"
]
},

"modelSelection": {
"title": "選擇模型",
"description": "啟動 OpenCode 後,在 TUI 中輸入以下命令查看/選擇模型:",
"command": "/models"
}
},

"startup": {
"title": "啟動 opencode",
"description": "在項目目錄下運行:",
"initNote": "首次啟動時,opencode 會加載配置並創建會話。"
},

"commonIssues": {
"title": "常見問題",

"commandNotFound": "1. 命令未找到",
"commandNotFoundWindows": [
"如果使用 npm 安裝,請確保 npm 全局路徑已添加到系統 PATH",
"重新打開終端窗口後再試"
],
"commandNotFoundUnix": "檢查安裝路徑並添加到 PATH(例如 ~/.local/bin 或 npm 全局目錄)",

"connectionFailed": "2. API 連接失敗",
"updateCli": "3. 更新 opencode"
}
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) 检测 JSON 重复 key(包含顶级与嵌套对象)
echo "=== Checking for duplicate keys in JSON ==="
python - <<'PY'
import json
import pathlib

def no_dupe_object_pairs_hook(pairs):
    obj = {}
    for k, v in pairs:
        if k in obj:
            raise ValueError(f"duplicate key: {k!r}")
        obj[k] = v
    return obj

try:
    p = pathlib.Path("messages/zh-TW/usage.json")
    s = p.read_text(encoding="utf-8")
    json.loads(s, object_pairs_hook=no_dupe_object_pairs_hook)
    print("✓ OK: no duplicate keys detected in messages/zh-TW/usage.json")
except ValueError as e:
    print(f"✗ ERROR: {e}")
except Exception as e:
    print(f"✗ Exception: {e}")
PY

echo ""
echo "=== Checking for opencode-related code in src/ ==="
# 2) 搜索渲染端是否直接读取 usage.opencode.installation.*.command 等字段
rg -n "usage\.opencode|installation.*command" src 2>/dev/null || echo "(no matches found in src/)"

echo ""
echo "=== Checking file structure and command field distribution ==="
python - <<'PY'
import json
import pathlib

p = pathlib.Path("messages/zh-TW/usage.json")
data = json.loads(p.read_text(encoding="utf-8"))

if "opencode" in data and "installation" in data["opencode"]:
    inst = data["opencode"]["installation"]
    print("Installation methods and their command field:")
    for key, val in inst.items():
        if isinstance(val, dict):
            has_cmd = "command" in val
            has_desc = "description" in val
            has_title = "title" in val
            print(f"  {key}: command={has_cmd}, description={has_desc}, title={has_title}")
            if isinstance(val, dict) and "command" in val:
                print(f"    → {val['command'][:50]}...")
        else:
            print(f"  {key}: {type(val).__name__} (not a dict)")
PY

Repository: ding113/claude-code-hub

Length of output: 153


🏁 Script executed:

#!/bin/bash

# 1) Check for duplicate keys in the JSON file
echo "=== Checking for duplicate keys in JSON ==="
python3 <<'PY'
import json
import pathlib

def detect_dupes(pairs):
    obj = {}
    for k, v in pairs:
        if k in obj:
            raise ValueError(f"Duplicate key found: {k!r}")
        obj[k] = v
    return obj

try:
    p = pathlib.Path("messages/zh-TW/usage.json")
    s = p.read_text(encoding="utf-8")
    json.loads(s, object_pairs_hook=detect_dupes)
    print("✓ No duplicate keys found")
except ValueError as e:
    print(f"✗ {e}")
except Exception as e:
    print(f"✗ Error: {e}")
PY

echo ""
echo "=== Checking command field distribution in opencode.installation ==="
python3 <<'PY'
import json
from pathlib import Path

data = json.loads(Path("messages/zh-TW/usage.json").read_text(encoding="utf-8"))
inst = data["opencode"]["installation"]

print("Installation methods:")
for key in inst:
    val = inst[key]
    if isinstance(val, dict):
        cmd_exists = "command" in val
        print(f"  - {key}: command={'✓' if cmd_exists else '✗'}")
        if cmd_exists:
            print(f"      value: {val['command']}")
PY

echo ""
echo "=== Checking for frontend code that references opencode ==="
# Simple grep in common UI/template locations
fd -e vue -e jsx -e tsx -e ts -e js src 2>/dev/null | head -20 || echo "(checking file structure)"

Repository: ding113/claude-code-hub

Length of output: 395


🏁 Script executed:

#!/bin/bash

echo "=== Full opencode.installation nested structure ==="
python3 <<'PY'
import json
from pathlib import Path

data = json.loads(Path("messages/zh-TW/usage.json").read_text(encoding="utf-8"))
inst = data["opencode"]["installation"]

def check_commands(obj, prefix=""):
    if isinstance(obj, dict):
        for k, v in obj.items():
            path = f"{prefix}.{k}" if prefix else k
            if isinstance(v, dict):
                check_commands(v, path)
            elif k == "command":
                print(f"  {path}: {v}")
    
check_commands(inst)
PY

echo ""
echo "=== Search for opencode references in entire repo ==="
rg "opencode" --max-count=10 -l 2>/dev/null | head -20 || echo "(no matches or error)"

echo ""
echo "=== Repository structure ==="
find . -maxdepth 2 -type d -name "src" -o -name "components" -o -name "pages" 2>/dev/null | head -10

Repository: ding113/claude-code-hub

Length of output: 559


🏁 Script executed:

#!/bin/bash

echo "=== Checking usage-doc page component for opencode rendering ==="
cat src/app/\[locale\]/usage-doc/page.tsx | head -100

echo ""
echo "=== Searching for command field usage in usage-doc related files ==="
rg "command" src/app/\[locale\]/usage-doc/ tests/unit/usage-doc/ -A 2 -B 2 2>/dev/null | head -50

Repository: ding113/claude-code-hub

Length of output: 6332


🏁 Script executed:

#!/bin/bash

echo "=== All opencode command field references in frontend ==="
rg "opencode\.installation\." src/ -o --no-heading 2>/dev/null | sort -u

echo ""
echo "=== Checking what fields are actually accessed for each installation method ==="
rg 't\("opencode\.installation' src/ -o 2>/dev/null | sort -u

Repository: ding113/claude-code-hub

Length of output: 325


🏁 Script executed:

#!/bin/bash

echo "=== Extracting exact opencode.installation field references ==="
rg 't\("opencode\.installation\.[^"]+' src/app/\[locale\]/usage-doc/page.tsx -o 2>/dev/null | sort -u

echo ""
echo "=== Viewing relevant section of page.tsx that handles opencode ==="
rg -A 30 "opencode" src/app/\[locale\]/usage-doc/page.tsx 2>/dev/null | head -80

Repository: ding113/claude-code-hub

Length of output: 3164


🏁 Script executed:

#!/bin/bash

echo "=== Complete opencode rendering for macOS and Linux ==="
rg -A 50 'os === "macos"' src/app/\[locale\]/usage-doc/page.tsx 2>/dev/null | grep -A 50 "opencode" | head -80

echo ""
echo "=== Check if script.command or npm.command are used anywhere ==="
rg "opencode\.installation\.(script|npm|macos|linux)" src/ -A 2 2>/dev/null | grep -i command

Repository: ding113/claude-code-hub

Length of output: 3246


建议统一 opencode installation 各方法的 command 字段定义位置,避免维护割裂。

验证确认:JSON 文件无重复键。但前端代码中,Windows 的 choco/scoop 方法从 JSON 获取 command 字段,而 macOS 的 homebrew、Linux、script 和 npm 的安装命令都硬编码在 React 组件中(分别为 brew install anomalyco/tap/opencodecurl -fsSL https://opencode.ai/install | bashnpm install -g opencode-ai)。这种混合模式导致维护不一致:命令更新需同时修改 JSON 和代码,容易遗漏。建议统一将所有 installation 方法的 command 字段迁入 JSON,或将所有命令硬编码在组件中。

🤖 Prompt for AI Agents
In @messages/zh-TW/usage.json around lines 472 - 558, The installation commands
are inconsistently sourced: only opencode.installation.windows.choco.command and
.scoop.command exist in the JSON while macOS (homebrew), linux, script and npm
commands are hardcoded in the React UI; update the JSON by adding a "command"
field under opencode.installation.homebrew, opencode.installation.linux,
opencode.installation.script and opencode.installation.npm (matching the
existing windows.*.command shape) and refactor the React component to read these
commands from the JSON keys (opencode.installation.*.command) instead of using
the hardcoded strings so all install commands are maintained in one place.

@ding113 ding113 merged commit d0cb42b into dev Jan 10, 2026
@github-project-automation github-project-automation bot moved this from Backlog to Done in Claude Code Hub Roadmap Jan 10, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
tests/unit/usage-doc/usage-doc-page.test.tsx (2)

36-56: 建议简化不必要的 async/await 声明

renderWithIntl 函数及其返回的 unmount 方法被声明为 async,但内部并未执行任何异步操作。在 React 19 中,root.render()root.unmount() 都是同步方法。虽然这不会导致功能问题,但会增加代码复杂度和误导性。

♻️ 简化建议
-async function renderWithIntl(locale: string, node: ReactNode) {
+function renderWithIntl(locale: string, node: ReactNode) {
   const container = document.createElement("div");
   document.body.appendChild(container);
   const root = createRoot(container);
   const usageMessages = loadUsageMessages(locale);
 
-  await act(async () => {
+  act(() => {
     root.render(
       <NextIntlClientProvider locale={locale} messages={{ usage: usageMessages }} timeZone="UTC">
         {node}
       </NextIntlClientProvider>
     );
   });
 
   return {
-    unmount: async () => {
-      await act(async () => root.unmount());
+    unmount: () => {
+      act(() => root.unmount());
       container.remove();
     },
   };
 }

然后更新调用处:

-const { unmount } = await renderWithIntl("en", <UsageDocPage />);
+const { unmount } = renderWithIntl("en", <UsageDocPage />);
 ...
-await unmount();
+unmount();

90-96: 建议使用更可靠的异步等待机制

当前使用 setTimeout(r, 0) 轮询等待 TOC 按钮出现的方式较为脆弱。如果目录渲染需要更长时间(例如在 CI 环境中),测试可能会不稳定。

♻️ 改进建议

考虑使用明确的等待条件,或使用测试库提供的 waitFor 工具:

-    let tocButtons = tocNav?.querySelectorAll("button") ?? [];
-    for (let i = 0; i < 10 && tocButtons.length === 0; i++) {
-      await act(async () => {
-        await new Promise((r) => setTimeout(r, 0));
-      });
-      tocButtons = tocNav?.querySelectorAll("button") ?? [];
-    }
+    // 等待目录按钮渲染完成
+    let tocButtons: NodeListOf<Element> | Element[] = [];
+    let attempts = 0;
+    const maxAttempts = 20; // 增加尝试次数
+    const waitMs = 50; // 使用更明确的等待时间
+    
+    while (tocButtons.length === 0 && attempts < maxAttempts) {
+      await act(async () => {
+        await new Promise((resolve) => setTimeout(resolve, waitMs));
+      });
+      tocButtons = tocNav?.querySelectorAll("button") ?? [];
+      attempts++;
+    }

或者,如果可用的话,使用专门的等待工具:

// 如果引入 @testing-library/react,可以使用:
import { waitFor } from '@testing-library/react';

await waitFor(() => {
  const buttons = tocNav?.querySelectorAll("button") ?? [];
  expect(buttons.length).toBeGreaterThan(0);
}, { timeout: 3000 });
src/app/[locale]/usage-doc/page.tsx (1)

1379-1436: 考虑使用映射对象替代深层嵌套三元表达式。

当前多处使用 4-5 层嵌套的三元表达式来选择 i18n key(如 titleKeycmdNotFoundKey 等),随着 CLI 工具增加会越来越难以维护。

♻️ 建议使用映射对象重构
// 示例:使用映射对象简化 key 选择
const commonIssuesKeys: Record<string, { title: string; cmdNotFound: string; /* ... */ }> = {
  "claude-code": {
    title: "claudeCode.commonIssues.title",
    cmdNotFound: "claudeCode.commonIssues.commandNotFound",
    // ...
  },
  codex: {
    title: "codex.commonIssues.title",
    cmdNotFound: "codex.commonIssues.commandNotFound",
    // ...
  },
  opencode: {
    title: "opencode.commonIssues.title",
    cmdNotFound: "opencode.commonIssues.commandNotFound",
    // ...
  },
  // ...
};

const keys = commonIssuesKeys[cli.id];
// 使用 keys.title, keys.cmdNotFound 等
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

📥 Commits

Reviewing files that changed from the base of the PR and between 5e173dc and fb627a6.

📒 Files selected for processing (8)
  • messages/en/usage.json
  • messages/ja/usage.json
  • messages/ru/usage.json
  • messages/zh-CN/usage.json
  • messages/zh-TW/usage.json
  • src/app/[locale]/usage-doc/page.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
  • tests/unit/usage-doc/usage-doc-page.test.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • messages/zh-TW/usage.json
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

No emoji characters in any code, comments, or string literals

Files:

  • tests/unit/usage-doc/usage-doc-page.test.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
  • src/app/[locale]/usage-doc/page.tsx
**/*.{ts,tsx,jsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,jsx,js}: All user-facing strings must use i18n (5 languages supported: zh-CN, en, ja, ko, de). Never hardcode display text
Use path alias @/ to map to ./src/
Use Biome for code formatting with configuration: double quotes, trailing commas, 2-space indent, 100 character line width
Prefer named exports over default exports
Use next-intl for internationalization
Use Next.js 16 App Router with Hono for API routes

Files:

  • tests/unit/usage-doc/usage-doc-page.test.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
  • src/app/[locale]/usage-doc/page.tsx
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Place unit tests in tests/unit/, integration tests in tests/integration/, and source-adjacent tests in src/**/*.test.ts

Files:

  • tests/unit/usage-doc/usage-doc-page.test.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use React 19, shadcn/ui, Tailwind CSS, and Recharts for the UI layer

Files:

  • tests/unit/usage-doc/usage-doc-page.test.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
  • src/app/[locale]/usage-doc/page.tsx
🧠 Learnings (7)
📚 Learning: 2026-01-07T17:05:37.171Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-07T17:05:37.171Z
Learning: Applies to **/*.{ts,tsx,jsx,js} : Use next-intl for internationalization

Applied to files:

  • tests/unit/usage-doc/usage-doc-page.test.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
📚 Learning: 2026-01-07T17:05:37.171Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-07T17:05:37.171Z
Learning: Applies to **/*.{ts,tsx,jsx,js} : All user-facing strings must use i18n (5 languages supported: zh-CN, en, ja, ko, de). Never hardcode display text

Applied to files:

  • tests/unit/usage-doc/usage-doc-page.test.tsx
  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
  • messages/zh-CN/usage.json
📚 Learning: 2026-01-07T17:05:37.171Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-07T17:05:37.171Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Place unit tests in tests/unit/, integration tests in tests/integration/, and source-adjacent tests in src/**/*.test.ts

Applied to files:

  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
📚 Learning: 2026-01-10T06:20:04.478Z
Learnt from: NieiR
Repo: ding113/claude-code-hub PR: 573
File: src/actions/model-prices.ts:275-335
Timestamp: 2026-01-10T06:20:04.478Z
Learning: In the `ding113/claude-code-hub` repository, Server Actions (files under `src/actions/*.ts`) currently return hardcoded Chinese error messages directly. This is a codebase-wide architectural decision that applies to all action files (e.g., model-prices.ts, users.ts, system-config.ts). Changing this pattern requires a coordinated i18n refactor across all Server Actions, which should be handled as a separate unified task rather than piecemeal changes in individual PRs.

Applied to files:

  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
  • messages/zh-CN/usage.json
  • src/app/[locale]/usage-doc/page.tsx
📚 Learning: 2026-01-10T06:20:19.207Z
Learnt from: NieiR
Repo: ding113/claude-code-hub PR: 573
File: messages/ja/dashboard.json:1342-1345
Timestamp: 2026-01-10T06:20:19.207Z
Learning: In this project, minor i18n formatting issues (such as spacing between numbers and units in Japanese/Chinese) are accepted when fixing them would require adding template complexity. The approach prioritizes code simplicity over perfect locale-specific formatting for minor cosmetic issues.

Applied to files:

  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
📚 Learning: 2026-01-05T03:02:14.502Z
Learnt from: NieiR
Repo: ding113/claude-code-hub PR: 539
File: src/app/[locale]/dashboard/_components/user/user-key-table-row.tsx:66-66
Timestamp: 2026-01-05T03:02:14.502Z
Learning: In the claude-code-hub project, the translations.actions.addKey field in UserKeyTableRowProps is defined as optional for backward compatibility, but all actual callers in the codebase provide the complete translations object. The field has been added to all 5 locale files (messages/{locale}/dashboard.json).

Applied to files:

  • tests/unit/usage-doc/opencode-usage-doc.test.tsx
📚 Learning: 2026-01-07T17:05:56.313Z
Learnt from: CR
Repo: ding113/claude-code-hub PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-07T17:05:56.313Z
Learning: Follow the coding standards and guidelines defined in CLAUDE.md

Applied to files:

  • src/app/[locale]/usage-doc/page.tsx
🧬 Code graph analysis (2)
tests/unit/usage-doc/usage-doc-page.test.tsx (1)
src/app/[locale]/usage-doc/page.tsx (1)
  • UsageDocPage (1750-1911)
tests/unit/usage-doc/opencode-usage-doc.test.tsx (1)
src/app/[locale]/usage-doc/page.tsx (1)
  • UsageDocContent (138-1742)
🔇 Additional comments (17)
messages/ja/usage.json (1)

476-576: LGTM!OpenCode 日语文档结构完整

该 OpenCode 使用指南的日语翻译结构完整,涵盖了安装、配置、启动和常见问题等所有必要部分,与其他 CLI 工具的文档格式保持一致。翻译内容专业且准确。

tests/unit/usage-doc/usage-doc-page.test.tsx (1)

58-76: 测试用例结构良好

该测试用例通过设置 cookie 模拟登录状态,验证了无障碍跳转链接和导航元素的渲染。测试逻辑清晰,断言合理。

tests/unit/usage-doc/opencode-usage-doc.test.tsx (4)

26-46: LGTM!测试辅助函数实现正确

renderWithIntl 辅助函数正确地使用了 React 19 的同步渲染 API,没有不必要的 async/await 声明。这是处理 React 19 测试的推荐方式。


48-61: 文档顺序验证测试设计良好

该测试用例通过检查 h2 标题的 ID 顺序,确保 OpenCode 章节正确地位于 Gemini CLI 和 Droid 之间,符合 PR 目标中描述的文档结构要求。


63-86: 配置示例验证全面

该测试用例验证了 OpenCode 配置文件包含所有必需的元素:JSON schema、cch 端点、三个主要 AI SDK 包以及 Claude、GPT 和 Gemini 的具体模型版本。负向断言(第 74 行)确保没有使用不必要的兼容包,体现了良好的测试设计。


88-124: 安装方式和国际化测试覆盖完整

两个测试用例分别验证了:

  1. 所有主流平台和包管理器的安装命令(curl、npm、bun、Homebrew、paru、Chocolatey、Scoop)
  2. 五种语言环境中 OpenCode 相关翻译键的完整性

测试覆盖了 PR 目标中提到的所有安装方法和国际化支持。

messages/en/usage.json (1)

476-576: 【严重】JSON 文件中存在重复的 opencode 顶层键

根据 AI 摘要的分析,该文件包含两个相同的顶层 opencode 对象。JSON 规范不支持同一层级的重复键,只有最后一个定义会生效,前面的定义会被覆盖。这会导致内容丢失或不可预测的行为。

🔧 修复方案

请检查完整文件内容,移除重复的 opencode 定义,只保留一个完整的 opencode 配置块。

 {
   ...
   "gemini": { ... },
-  "opencode": { ... },  // 删除重复的第一个或第二个
   "opencode": { ... },
   "droid": { ... }
 }

可以使用 JSON lint 工具验证文件的有效性:

#!/bin/bash
# 验证 JSON 文件结构并检测重复键
python -c "
import json
import sys
with open('messages/en/usage.json', 'r', encoding='utf-8') as f:
    content = f.read()
    # 检测重复键
    if content.count('\"opencode\":') > 1:
        print('ERROR: Duplicate opencode key found')
        sys.exit(1)
    json.loads(content)
    print('OK: Valid JSON structure')
"

Likely an incorrect or invalid review comment.

messages/ru/usage.json (1)

476-576: 【严重】JSON 文件中存在重复的 opencode 顶层键

根据 AI 摘要的分析,该文件包含两个完全相同的顶层 opencode 对象定义。在 JSON 中,重复的键是无效的,解析器只会保留最后出现的定义,导致前面的配置被覆盖丢失。

🔧 修复方案

请删除重复的 opencode 定义,确保文件中只有一个 opencode 配置块。

 {
   ...
   "gemini": { ... },
-  "opencode": { ... },  // 删除其中一个重复定义
   "opencode": { ... },
   "droid": { ... }
 }

建议运行以下验证脚本:

#!/bin/bash
# 检查俄语 usage.json 中的重复键
python3 << 'EOF'
import json
import sys

try:
    with open('messages/ru/usage.json', 'r', encoding='utf-8') as f:
        content = f.read()
        # 统计 opencode 键出现次数
        count = content.count('"opencode":')
        if count > 1:
            print(f'错误:发现 {count} 个重复的 opencode 键')
            sys.exit(1)
        # 验证 JSON 语法
        json.loads(content)
        print('验证通过:JSON 结构有效')
except Exception as e:
    print(f'验证失败:{e}')
    sys.exit(1)
EOF

Likely an incorrect or invalid review comment.

messages/zh-CN/usage.json (1)

472-572: LGTM! OpenCode i18n 结构完整且与其他 CLI 部分保持一致。

新增的 opencode 部分结构良好,包含 installationconfigurationstartupcommonIssues 子部分,与现有的 claudeCodecodexgeminidroid 部分保持一致的结构模式。

src/app/[locale]/usage-doc/page.tsx (8)

51-56: LGTM! requiresNodeJs 字段设计合理。

新增的可选字段 requiresNodeJs 通过布尔值明确控制是否展示 Node.js 环境准备步骤,比之前基于 packageName 的隐式判断更清晰。


113-119: LGTM! OpenCode CLI 配置正确。

requiresNodeJs: false 设置正确,因为 OpenCode 支持多种安装方式(官方脚本、Homebrew、Chocolatey/Scoop 等),Node.js 并非必需依赖。


960-1065: LGTM! OpenCode 安装渲染逻辑完整。

函数正确处理了三个操作系统的安装方式:

  • Windows: Chocolatey、Scoop、npm
  • macOS/Linux: 官方脚本、Homebrew、npm、Bun
  • Linux 特有: Paru (Arch Linux AUR)

所有用户可见文本均使用 t() 进行国际化处理。


1076-1122: 配置示例中的模型版本号需确认。

配置 JSON 中包含的模型版本号(如 claude-haiku-4-5-20251001claude-opus-4-5-20251101gemini-3-pro-previewgpt-5.2)看起来是面向未来的模型标识符。请确认这些是预期的模型 ID,或者是否应该使用当前可用的模型版本。


1638-1649: LGTM! OpenCode 章节位置正确。

OpenCode 使用指南章节正确放置在 Gemini CLI 之后、Droid CLI 之前,符合 PR 目标描述。结构与其他 CLI 章节保持一致。


138-138: LGTM! 导出 UsageDocContent 有利于测试。

UsageDocContent 改为命名导出符合编码规范,且便于单元测试直接导入和验证组件行为。


1532-1539: LGTM! requiresNodeJs 条件渲染正确。

使用 cli.requiresNodeJs 显式控制 Node.js 环境准备部分的显示,逻辑清晰且易于维护。


1376-1378: LGTM! 环境变量名称分组正确。

codexopencode 使用 CCH_API_KEY,与各自配置文件中的设置一致(OpenCode 配置中使用 {env:CCH_API_KEY})。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:docs area:i18n documentation Improvements or additions to documentation size/L Large PR (< 1000 lines)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant