diff --git a/README.md b/README.md index 7e16aff6..d5be8ee4 100644 --- a/README.md +++ b/README.md @@ -44,14 +44,14 @@ v0.5.0 shipped a full UI redesign — six colour themes that can follow your sys - - - + + + - - - + + +
Desktop session view
Say it once, watch it finish
Tool calls and every edit stay in the thread
Workspace diff review
See exactly what changed
Syntax-highlighted diffs; you decide what lands
Built-in browser previewing the page that was just changed
Verify on the spot
Open your dev server inside the app
Desktop session view
Say it once, watch it finish
Tool calls and every edit stay in the thread
Workspace diff review
See exactly what changed
Syntax-highlighted diffs; you decide what lands
Built-in browser previewing the page that was just changed
Verify on the spot
Open your dev server inside the app
Session view in the dark theme
Six themes, follows the system
Light and dark, six palettes in all
Skill marketplace
Missing a trick? Install it
Source and safety status shown up front
Desktop pet settings with the floating pet
Company while it works
Dada, Huhu, Bubu and Huihui follow the task
Session view in the dark theme
Six themes, follows the system
Light and dark, six palettes in all
Skill marketplace
Missing a trick? Install it
Source and safety status shown up front
Desktop pet settings with the floating pet
Company while it works
Dada, Huhu, Bubu and Huihui follow the task
@@ -138,16 +138,6 @@ This project is maintained in the author's spare time. Corporate or individual s --- -## User Group - -Scan the QR code below to join the cc-haha user group on Feishu (Lark) — the conversation there is mostly in Chinese. For questions and bug reports in English, [Issues](https://github.com/NanmiCoder/cc-haha/issues) is the better place. - -

- cc-haha Feishu user group QR code -

- ---- - ## ☕ Buy Me a Coffee If this project helps you, consider buying me a coffee — every bit of support keeps this project going ❤️ @@ -173,6 +163,16 @@ If this project helps you, consider buying me a coffee — every bit of support --- +## User Group + +Scan the QR code below to join the cc-haha user group on Feishu (Lark) — the conversation there is mostly in Chinese. For questions and bug reports in English, [Issues](https://github.com/NanmiCoder/cc-haha/issues) is the better place. + +

+ cc-haha Feishu user group QR code +

+ +--- + ## Tech Stack | Category | Technology | diff --git a/README.zh-CN.md b/README.zh-CN.md index 2c27be4a..301520e8 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -44,14 +44,14 @@ v0.5.0 做了一次全量 UI 重设计(「纸·墨·印」),六套配色 - - - + + + - - - + + +
桌面端会话主界面
说一句话,看它做完
工具调用和每处改动都留在对话里
工作区 Diff 评审
改了什么,逐个文件看
带语法高亮的 Diff,你点头才落地
内置浏览器预览刚改完的页面
改完当场验证
内置浏览器打开本地服务看效果
桌面端会话主界面
说一句话,看它做完
工具调用和每处改动都留在对话里
工作区 Diff 评审
改了什么,逐个文件看
带语法高亮的 Diff,你点头才落地
内置浏览器预览刚改完的页面
改完当场验证
内置浏览器打开本地服务看效果
墨夜主题下的会话界面
六套配色可跟随系统
纯白 · 纸墨 · 经典暖色 · 青瓷 · 墨夜 · 墨夜蓝
技能市场
缺什么手艺装什么
来源和安全状态摆在明处
桌面宠物设置与悬浮宠物
桌面上有个伴
搭搭、弧弧、补补、回回随任务换动作
墨夜主题下的会话界面
六套配色可跟随系统
纯白 · 纸墨 · 经典暖色 · 青瓷 · 墨夜 · 墨夜蓝
技能市场
缺什么手艺装什么
来源和安全状态摆在明处
桌面宠物设置与悬浮宠物
桌面上有个伴
搭搭、弧弧、补补、回回随任务换动作
@@ -138,16 +138,6 @@ cp .env.example .env --- -## 用户交流群 - -使用过程中有问题、想反馈 Bug,或者想看看别人怎么用,欢迎扫码加入 cc-haha 飞书用户群。也可以直接来 [Issues](https://github.com/NanmiCoder/cc-haha/issues) 提问。 - -

- cc-haha 飞书用户群二维码 -

- ---- - ## ☕ 请作者喝杯咖啡 如果这个项目对您有帮助,欢迎打赏支持,您的每一份支持都是我持续更新的动力 ❤️ @@ -173,6 +163,16 @@ cp .env.example .env --- +## 用户交流群 + +使用过程中有问题、想反馈 Bug,或者想看看别人怎么用,欢迎扫码加入 cc-haha 飞书用户群。也可以直接来 [Issues](https://github.com/NanmiCoder/cc-haha/issues) 提问。 + +

+ cc-haha 飞书用户群二维码 +

+ +--- + ## 技术栈 | 类别 | 技术 | diff --git a/docs/desktop/agents.md b/docs/desktop/agents.md index c80e51f2..a1b2e57a 100644 --- a/docs/desktop/agents.md +++ b/docs/desktop/agents.md @@ -38,7 +38,7 @@ order: 3 ## 看已经装了哪些 -![设置 → Agents:按来源分组的 Agent 浏览器](../images/app/settings-agents.webp) +![设置 → Agents:按来源分组的 Agent 浏览器](../images/app/zh-CN/settings-agents.webp) 打开 设置 → Agents。顶部三张卡是总数、生效中、来源类型数,下面按来源分组: @@ -53,7 +53,7 @@ order: 3 ## 捏一个自己的 -![「创建 Agent」弹窗:作用域、模型、思考强度、工具、系统提示词](../images/app/agent-create.webp) +![「创建 Agent」弹窗:作用域、模型、思考强度、工具、系统提示词](../images/app/zh-CN/agent-create.webp) 点右上角「创建 Agent」,要填的字段: diff --git a/docs/desktop/computer-use.md b/docs/desktop/computer-use.md index 0b9ec022..ada8417b 100644 --- a/docs/desktop/computer-use.md +++ b/docs/desktop/computer-use.md @@ -15,7 +15,7 @@ order: 7 ## 准备环境 -![设置 → Computer Use:环境检测、macOS 两项授权、已授权应用](../images/app/settings-computer-use.webp) +![设置 → Computer Use:环境与 Python 运行时检测](../images/app/zh-CN/settings-computer-use.webp) 打开 设置 → Computer Use,页面顶部是一排环境检查: diff --git a/docs/desktop/pets.md b/docs/desktop/pets.md index fd8d06c7..820106e2 100644 --- a/docs/desktop/pets.md +++ b/docs/desktop/pets.md @@ -20,7 +20,7 @@ order: 8 3. 从「内置宠物」里挑一个。 4. 打开「显示桌面宠物」。 -![设置 → 宠物:四只内置宠物与外观参数](../images/app/settings-pets.webp) +![设置 → 宠物:四只内置宠物与外观参数](../images/app/zh-CN/settings-pets.webp) ## 四只内置宠物 @@ -35,7 +35,7 @@ order: 8 ## 和它互动 -![桌宠悬浮在桌面上](../images/app/pet-desktop.webp) +![桌宠悬浮在桌面上](../images/app/zh-CN/pet-desktop.webp) - **悬停** — 空闲时它会跳一下,视线跟着你的指针转。 - **单击** — 唤起主窗口,同时挥个手。注意它只是把窗口叫出来,不会自动跳进某条会话。 diff --git a/docs/desktop/remote.md b/docs/desktop/remote.md index e44bbbaa..c141e712 100644 --- a/docs/desktop/remote.md +++ b/docs/desktop/remote.md @@ -16,7 +16,7 @@ order: 9 ## H5 访问 -![设置 → H5 访问:二维码与令牌](../images/app/settings-h5.webp) +![设置 → H5 访问:局域网访问开关与连接参数](../images/app/zh-CN/settings-h5.webp) ### 开启 @@ -27,7 +27,7 @@ order: 9 扫出来的链接里带着服务器地址和令牌,手机浏览器打开后会把连接信息存下来,之后直接打开就能用。 -![手机端的对话界面与文件变更卡](../images/app/h5-session.webp) +![手机端的对话界面与文件变更卡](../images/app/zh-CN/h5-session.webp) ### 令牌是访问凭据 @@ -65,7 +65,7 @@ H5 默认关闭,它也不是公开服务。开启前先确认你在自己信 ## IM 接入 -![设置 → IM 接入:配对管理与五个平台](../images/app/settings-im.webp) +![设置 → IM 接入:配对管理与五个平台](../images/app/zh-CN/settings-im.webp) 设置 → IM 接入 支持五个平台,接入方式各不相同: diff --git a/docs/desktop/schedule.md b/docs/desktop/schedule.md index 1bc837c4..d04a769f 100644 --- a/docs/desktop/schedule.md +++ b/docs/desktop/schedule.md @@ -21,7 +21,7 @@ order: 5 ## 新建任务的每个字段 -![「新建定时任务」弹窗:名称、描述、提示词、频率与通知](../images/app/schedule-create.webp) +![「新建定时任务」弹窗:名称、描述、提示词、频率与通知](../images/app/zh-CN/schedule-create.webp) - **名称**(必填)— 列表里显示的标识,建议用短横线风格,比如 `daily-code-review`。 - **描述**(必填)— 一句话说明这个任务干什么,方便以后自己认出来。 diff --git a/docs/desktop/sessions.md b/docs/desktop/sessions.md index 105fb810..5dc2f277 100644 --- a/docs/desktop/sessions.md +++ b/docs/desktop/sessions.md @@ -19,7 +19,7 @@ order: 1 ## 读懂对话流 -![一条完整会话:用户提问、工具调用卡、思考块、文件编辑与内联 diff](../images/app/session-main.webp) +![一条完整会话:用户提问、工具调用卡、思考块、文件编辑与内联 diff](../images/app/zh-CN/session-main.webp) Claude 干活时不是一句话回你,中间会插进来几种卡片: @@ -32,7 +32,7 @@ Claude 干活时不是一句话回你,中间会插进来几种卡片: ## 权限弹窗:三个按钮怎么选 -![「允许 Claude Edit index.html?」权限询问卡,下方是变更预览](../images/app/session-permission.webp) +![「允许 Claude Edit index.html?」权限询问卡,下方是变更预览](../images/app/zh-CN/session-permission.webp) 默认权限模式下,Claude 每次要改文件或跑高风险命令,都会停下来问你。弹窗里会先给出这次改动的预览,然后是三个按钮: @@ -84,7 +84,7 @@ Claude 每完成一轮,对话里会出现一张「{n} 个文件已更改」的 ## 输入框能干的事 -![输入 `/` 弹出的斜杠命令面板](../images/app/composer-slash.webp) +![输入 `/` 弹出的斜杠命令面板](../images/app/zh-CN/composer-slash.webp) - **`/` 斜杠命令** — 输入 `/` 弹出命令面板。`/status` 看会话状态和用量、`/context` 看上下文占用、`/compact` 压缩上下文、`/review` 审查改动、`/commit` 提交、`/memory` 打开项目记忆、`/doctor` 打开诊断检查。 - **`@` 引用文件** — 输入 `@` 弹出文件搜索,选中的文件会以路径形式附到消息上。 diff --git a/docs/desktop/settings.md b/docs/desktop/settings.md index 8371b7ae..ab0896ec 100644 --- a/docs/desktop/settings.md +++ b/docs/desktop/settings.md @@ -19,7 +19,7 @@ order: 6 最常动的一栏,配的都是「用起来顺不顺手」的东西。 -![设置 → 通用:配色主题、语言、输出风格、默认权限](../images/app/settings-general.webp) +![设置 → 通用:配色主题、语言、输出风格、默认权限](../images/app/zh-CN/settings-general.webp) - **配色主题** — 六套:纯白(默认)、纸墨、经典暖色、青瓷、墨夜、墨夜蓝。另有「跟随系统」开关,打开后可以分别指定浅色模式和深色模式各用哪一套。 - **语言** — 界面显示语言。 @@ -35,7 +35,7 @@ order: 6 - **界面缩放** — 整体放大缩小,也可以用 `⌘+` / `⌘-` 快捷键,`⌘0` 回到 100%。 - **数据存储位置** — 低频高级设置。默认用系统目录 `~/.claude`,也可以改成你指定的绝对路径。切换后会话记录、技能、MCP、插件、服务商配置全部从新目录读取,需要重启应用生效,两个目录之间不会自动合并或迁移。 -![同一条会话在「墨夜」深色主题下的样子](../images/app/session-dark.webp) +![同一条会话在「墨夜」深色主题下的样子](../images/app/zh-CN/session-dark.webp) ## H5 访问 @@ -91,7 +91,7 @@ Windows 用户可以在这里指定启动 Shell(系统默认 / PowerShell 7 / ## Token 用量 -![设置 → Token 用量:热力图与统计卡](../images/app/settings-usage.webp) +![设置 → Token 用量:热力图与统计卡](../images/app/zh-CN/settings-usage.webp) 基于本机 Claude Code 会话记录统计出来的用量看板,全部在本地算,不上传。 diff --git a/docs/desktop/skills.md b/docs/desktop/skills.md index bad03d8c..2cd4c0ac 100644 --- a/docs/desktop/skills.md +++ b/docs/desktop/skills.md @@ -13,7 +13,7 @@ order: 4 ## 技能市场 -![技能市场:卡片列表、安全徽标和来源筛选](../images/app/skill-market.webp) +![技能市场:卡片列表、安全徽标和来源筛选](../images/app/zh-CN/skill-market.webp) 点侧边栏的「技能市场」。它同时聚合 **ClawHub** 和 **SkillHub** 两个来源,列表往下滚会自动加载更多,没有「加载更多」按钮。 diff --git a/docs/desktop/workspace.md b/docs/desktop/workspace.md index 2111ae9c..ca97d1c7 100644 --- a/docs/desktop/workspace.md +++ b/docs/desktop/workspace.md @@ -20,7 +20,7 @@ order: 2 ## 已更改文件 / 所有文件 -![工作区「已更改文件」列表,每行带状态标记和增删行数](../images/app/workspace-changes.webp) +![工作区「已更改文件」列表,每行带状态标记和增删行数](../images/app/zh-CN/workspace-changes.webp) 文件模式下有两个视图: @@ -35,7 +35,7 @@ order: 2 ## Diff 评审:给某一行留话 -![Diff 评审界面,左右对照并带语法高亮](../images/app/workspace-diff.webp) +![Diff 评审界面,左右对照并带语法高亮](../images/app/zh-CN/workspace-diff.webp) Diff 保留旧行和新行,带语法高亮。真正有用的是行级评论: @@ -66,7 +66,7 @@ Diff 保留旧行和新行,带语法高亮。真正有用的是行级评论: ## 内置浏览器 -![内置浏览器预览刚改完的页面](../images/app/workspace-preview.webp) +![内置浏览器预览刚改完的页面](../images/app/zh-CN/workspace-preview.webp) 把工作区切到「浏览器」,地址栏里填本地开发地址或者任意网址就能预览。这里有三个专门为「让 Claude 看见」设计的按钮: diff --git a/docs/en/desktop/agents.md b/docs/en/desktop/agents.md index a63bd597..6b25ea8a 100644 --- a/docs/en/desktop/agents.md +++ b/docs/en/desktop/agents.md @@ -38,7 +38,7 @@ You can name one directly ("use Explore to find…") or let Claude decide who to ## Seeing what's installed -![Settings → Agents: the agent browser grouped by source](../../images/app/settings-agents.webp) +![Settings → Agents: the agent browser grouped by source](../../images/app/en/settings-agents.webp) Open **Settings → Agents**. Three cards at the top show total agents, how many are active, and how many sources are in play. Below that, agents are grouped by source in a fixed order: @@ -53,7 +53,7 @@ Click any row for its detail page: model, effort, tool scope, and the full syste ## Writing your own -![The Create Agent dialog: scope, model, effort, tools, system prompt](../../images/app/agent-create.webp) +![The Create Agent dialog: scope, model, effort, tools, system prompt](../../images/app/en/agent-create.webp) Click **Create Agent** in the top right. The fields: diff --git a/docs/en/desktop/computer-use.md b/docs/en/desktop/computer-use.md index e8422e2f..582af94a 100644 --- a/docs/en/desktop/computer-use.md +++ b/docs/en/desktop/computer-use.md @@ -15,7 +15,7 @@ macOS and Windows are supported. There is no Linux executor yet. ## Preparing the environment -![Settings → Computer Use: environment checks, the two macOS permissions, authorized apps](../../images/app/settings-computer-use.webp) +![Settings → Computer Use: environment and Python runtime checks](../../images/app/en/settings-computer-use.webp) Open **Settings → Computer Use**. The top of the page is a row of environment checks: diff --git a/docs/en/desktop/pets.md b/docs/en/desktop/pets.md index c77fd97b..8124fd25 100644 --- a/docs/en/desktop/pets.md +++ b/docs/en/desktop/pets.md @@ -20,7 +20,7 @@ The pet is **off by default**: 3. Pick one from **Built-in pets**. 4. Turn on **Show desktop pet**. -![Settings → Pets: four built-in pets and appearance controls](../../images/app/settings-pets.webp) +![Settings → Pets: four built-in pets and appearance controls](../../images/app/en/settings-pets.webp) ## The four built-in pets @@ -35,7 +35,7 @@ Switching characters updates an already-open pet window immediately. ## Interacting with it -![The pet floating on the desktop](../../images/app/pet-desktop.webp) +![The pet floating on the desktop](../../images/app/en/pet-desktop.webp) - **Hover** — while idle it hops, and its gaze follows your pointer. - **Click** — brings the main window forward with a wave. Note that it only raises the window; it doesn't jump into a particular session. diff --git a/docs/en/desktop/remote.md b/docs/en/desktop/remote.md index 4b426662..99f0a05c 100644 --- a/docs/en/desktop/remote.md +++ b/docs/en/desktop/remote.md @@ -16,7 +16,7 @@ Both require your computer to be on with the app running. They expose the local ## H5 Access -![Settings → H5 Access: QR code and token](../../images/app/settings-h5.webp) +![Settings → H5 Access: LAN access toggle and connection settings](../../images/app/en/settings-h5.webp) ### Turning it on @@ -27,7 +27,7 @@ Both require your computer to be on with the app running. They expose the local The scanned link carries the server address and the token. Once your phone's browser connects, it remembers the connection and later visits go straight in. -![The mobile conversation view with a file-changes card](../../images/app/h5-session.webp) +![The mobile conversation view with a file-changes card](../../images/app/en/h5-session.webp) ### The token is the credential @@ -65,7 +65,7 @@ The desktop workspace, embedded terminal, native "open with", Computer Use autho ## IM Adapters -![Settings → IM Adapters: pairing and the five platforms](../../images/app/settings-im.webp) +![Settings → IM Adapters: pairing and the five platforms](../../images/app/en/settings-im.webp) **Settings → IM Adapters** supports five platforms, each connected differently: diff --git a/docs/en/desktop/schedule.md b/docs/en/desktop/schedule.md index 1dab0e52..f8d71f47 100644 --- a/docs/en/desktop/schedule.md +++ b/docs/en/desktop/schedule.md @@ -21,7 +21,7 @@ Scheduled tasks only run while the desktop app is open and your computer is awak ## Every field in the form -![The New scheduled task dialog: name, description, prompt, frequency, notifications](../../images/app/schedule-create.webp) +![The New scheduled task dialog: name, description, prompt, frequency, notifications](../../images/app/en/schedule-create.webp) - **Name** (required) — the identifier in the list. A hyphenated form like `daily-code-review` reads well. - **Description** (required) — one line about what it does, so you recognize it later. diff --git a/docs/en/desktop/sessions.md b/docs/en/desktop/sessions.md index adb2efce..d7144354 100644 --- a/docs/en/desktop/sessions.md +++ b/docs/en/desktop/sessions.md @@ -19,7 +19,7 @@ The small line under the session title is metadata: project path, branch, model. ## Reading the conversation -![A full session: a question, tool cards, a thinking block, a file edit with an inline diff](../../images/app/session-main.webp) +![A full session: a question, tool cards, a thinking block, a file edit with an inline diff](../../images/app/en/session-main.webp) Claude doesn't just reply with a paragraph. Several kinds of card appear along the way: @@ -32,7 +32,7 @@ In a long conversation, `⌘F` opens find-in-page and jumps between matches in t ## The permission prompt: which button? -![The "Allow Claude to Edit index.html?" prompt with a preview of the change](../../images/app/session-permission.webp) +![The "Allow Claude to Edit index.html?" prompt with a preview of the change](../../images/app/en/session-permission.webp) In the default permission mode, Claude stops and asks before editing a file or running a risky command. The dialog previews the change, then offers three buttons: @@ -84,7 +84,7 @@ Tool activity from background subagents bubbles up here too, so you don't have t ## What the composer can do -![The slash-command panel that opens when you type `/`](../../images/app/composer-slash.webp) +![The slash-command panel that opens when you type `/`](../../images/app/en/composer-slash.webp) - **`/` slash commands** — type `/` for the command panel. `/status` for session state and usage, `/context` for context breakdown, `/compact` to compress, `/review` to review changes, `/commit`, `/memory` to open project memory, `/doctor` to open the diagnostics check. - **`@` file references** — type `@` for file search; the file you pick is attached to the message as a path. diff --git a/docs/en/desktop/settings.md b/docs/en/desktop/settings.md index 45728337..b867e1c4 100644 --- a/docs/en/desktop/settings.md +++ b/docs/en/desktop/settings.md @@ -19,7 +19,7 @@ You'll come here once during setup and rarely again. Full steps in [Connecting a The tab you'll open most often — everything about how the app feels. -![Settings → General: color themes, language, output style, default permissions](../../images/app/settings-general.webp) +![Settings → General: color themes, language, output style, default permissions](../../images/app/en/settings-general.webp) - **Color theme** — six of them: Pure White (default), Paper, Warm Classic, Celadon, Ink Night, Ink Blue. There's also **Follow the system**, which lets you pick which theme to use in light mode and which in dark mode. - **Language** — the interface language. @@ -35,7 +35,7 @@ The tab you'll open most often — everything about how the app feels. - **UI Zoom** — scale the whole interface, also bound to `⌘+` / `⌘-`, with `⌘0` back to 100%. - **Data Storage Location** — an advanced, rarely-touched setting. Defaults to the system directory `~/.claude`, or point it at an absolute path of your own. After switching, sessions, skills, MCP, plugins, and provider config are all read from the new directory; it needs a restart, and the two directories are never merged or migrated automatically. -![The same session in the Ink Night dark theme](../../images/app/session-dark.webp) +![The same session in the Ink Night dark theme](../../images/app/en/session-dark.webp) ## H5 Access @@ -91,7 +91,7 @@ Let Claude read the screen, click, and type. Unusable until you install the runt ## Token usage -![Settings → Token usage: heatmap and stat cards](../../images/app/settings-usage.webp) +![Settings → Token usage: heatmap and stat cards](../../images/app/en/settings-usage.webp) A usage dashboard computed from the Claude Code session records on this machine. Everything is calculated locally and nothing is uploaded. diff --git a/docs/en/desktop/skills.md b/docs/en/desktop/skills.md index e2e07083..e3f11983 100644 --- a/docs/en/desktop/skills.md +++ b/docs/en/desktop/skills.md @@ -13,7 +13,7 @@ A skill is a procedure someone else already worked out. Install it and Claude fo ## The Skills Market -![The Skills Market: cards, security badges, source filters](../../images/app/skill-market.webp) +![The Skills Market: cards, security badges, source filters](../../images/app/en/skill-market.webp) Click **Skills Market** in the sidebar. It aggregates two sources, **ClawHub** and **SkillHub**, and loads more as you scroll — there is no "load more" button. diff --git a/docs/en/desktop/workspace.md b/docs/en/desktop/workspace.md index fdeef414..b9230f24 100644 --- a/docs/en/desktop/workspace.md +++ b/docs/en/desktop/workspace.md @@ -20,7 +20,7 @@ At the top of the panel is a **Files / Browser** switch: ## Changed files and All files -![The "Changed files" list, each row with a status marker and line counts](../../images/app/workspace-changes.webp) +![The "Changed files" list, each row with a status marker and line counts](../../images/app/en/workspace-changes.webp) In Files mode there are two views: @@ -35,7 +35,7 @@ Any file can have its path copied, or be pushed back into the composer as contex ## Diff review: leaving a note on a line -![Diff review with syntax highlighting, old and new side by side](../../images/app/workspace-diff.webp) +![Diff review with syntax highlighting, old and new side by side](../../images/app/en/workspace-diff.webp) The diff keeps old and new lines with full syntax highlighting. The genuinely useful part is line-level comments: @@ -66,7 +66,7 @@ The temporary worktree is cleaned up when you're done. History stays readable, b ## Built-in browser -![The built-in browser previewing a page that was just edited](../../images/app/workspace-preview.webp) +![The built-in browser previewing a page that was just edited](../../images/app/en/workspace-preview.webp) Switch the workspace panel to **Browser** and type a local dev address or any URL. Three buttons here exist specifically so Claude can see what you see: diff --git a/docs/en/im/index.md b/docs/en/im/index.md index a998ccdf..a2486e59 100644 --- a/docs/en/im/index.md +++ b/docs/en/im/index.md @@ -11,7 +11,7 @@ A session running in the Desktop app can be reached from a private chat on your The chat partner is a bot or account you bound yourself. Messages reach your local Desktop app; no intermediate service holds your code. -![Settings shows pairing management on top and one tab per platform](../../images/app/settings-im.webp) +![Settings shows pairing management on top and one tab per platform](../../images/app/en/settings-im.webp) ## What you get diff --git a/docs/en/start/first-session.md b/docs/en/start/first-session.md index 0472923e..498c0caf 100644 --- a/docs/en/start/first-session.md +++ b/docs/en/start/first-session.md @@ -13,7 +13,7 @@ Your model is connected. Now let it actually do something. Find a project you do Click "New session" in the sidebar, or press `Cmd/Ctrl + N`. -![Empty session, with permission mode, launch location, and model controls in the composer](../../images/app/session-new.webp) +![Empty session, with permission mode, launch location, and model controls in the composer](../../images/app/en/session-new.webp) Look at the row along the bottom of the composer: `+` for attachments, then **permission mode**, **launch location**, **model and effort**, and finally "Run". @@ -25,7 +25,7 @@ If the folder is a Git repository, the same pill also lets you choose a branch a Click the permission mode button and all five levels open up. -![The five permission modes](../../images/app/permission-modes.webp) +![The five permission modes](../../images/app/en/permission-modes.webp) | Mode | What the app says it does | |---|---| @@ -68,7 +68,7 @@ Press `Enter` to send (`Shift + Enter` for a newline). ## 4. Watch it work -![A full turn: collapsed tool calls, thinking, a permission prompt, an inline diff](../../images/app/session-main.webp) +![A full turn: collapsed tool calls, thinking, a permission prompt, an inline diff](../../images/app/en/session-main.webp) It orients itself before it starts editing, and you'll see several kinds of card go by: diff --git a/docs/en/start/index.md b/docs/en/start/index.md index 3ba8adf2..8aae4a19 100644 --- a/docs/en/start/index.md +++ b/docs/en/start/index.md @@ -9,7 +9,7 @@ order: 0 It's an app on your computer. You hand it a project folder, describe what you want in plain language, and it goes off to read the code, edit files, and run commands — with every change laid out in front of you, waiting for your approval. -![A full session: prompt, tool calls, file edits, inline diff](../../images/app/session-main.webp) +![A full session: prompt, tool calls, file edits, inline diff](../../images/app/en/session-main.webp) That's a real session. Projects and history on the left, the conversation in the middle, and when Claude edits a file the diff appears right underneath, line by line. diff --git a/docs/en/start/models.md b/docs/en/start/models.md index ed7bd853..6ce99e24 100644 --- a/docs/en/start/models.md +++ b/docs/en/start/models.md @@ -67,7 +67,7 @@ Whether a local model can actually sustain an agent workflow comes down to its t ## The Add Provider dialog, field by field -![Add Provider dialog: preset, base URL, auth variable, API key, model mapping](../../images/app/settings-provider-add.webp) +![Add Provider dialog: preset, base URL, auth variable, API key, model mapping](../../images/app/en/settings-provider-add.webp) **Name** (required) — how this provider appears in the list. A preset fills it in; rename it to something you'll recognize, like "DeepSeek — work account". diff --git a/docs/im/index.md b/docs/im/index.md index 368e2291..aba81f9c 100644 --- a/docs/im/index.md +++ b/docs/im/index.md @@ -11,7 +11,7 @@ order: 0 对话对象是你自己绑定的机器人或账号,消息只经过你本机的桌面端,没有中间服务器托管你的代码。 -![设置里的 IM 接入页,顶部是配对管理,下面是五个平台 Tab](../images/app/settings-im.webp) +![设置里的 IM 接入页,顶部是配对管理,下面是五个平台 Tab](../images/app/zh-CN/settings-im.webp) ## 接进来之后能做什么 diff --git a/docs/images/app/agent-create.webp b/docs/images/app/agent-create.webp deleted file mode 100644 index fb9d6353..00000000 Binary files a/docs/images/app/agent-create.webp and /dev/null differ diff --git a/docs/images/app/composer-mention.webp b/docs/images/app/composer-mention.webp deleted file mode 100644 index c4126030..00000000 Binary files a/docs/images/app/composer-mention.webp and /dev/null differ diff --git a/docs/images/app/composer-slash.webp b/docs/images/app/composer-slash.webp deleted file mode 100644 index dfcea60f..00000000 Binary files a/docs/images/app/composer-slash.webp and /dev/null differ diff --git a/docs/images/app/en/agent-create.webp b/docs/images/app/en/agent-create.webp new file mode 100644 index 00000000..cfd98263 Binary files /dev/null and b/docs/images/app/en/agent-create.webp differ diff --git a/docs/images/app/en/composer-mention.webp b/docs/images/app/en/composer-mention.webp new file mode 100644 index 00000000..03fb2e78 Binary files /dev/null and b/docs/images/app/en/composer-mention.webp differ diff --git a/docs/images/app/en/composer-slash.webp b/docs/images/app/en/composer-slash.webp new file mode 100644 index 00000000..3dd65d03 Binary files /dev/null and b/docs/images/app/en/composer-slash.webp differ diff --git a/docs/images/app/en/h5-session.webp b/docs/images/app/en/h5-session.webp new file mode 100644 index 00000000..1182966b Binary files /dev/null and b/docs/images/app/en/h5-session.webp differ diff --git a/docs/images/app/en/h5-sessions.webp b/docs/images/app/en/h5-sessions.webp new file mode 100644 index 00000000..2d23563c Binary files /dev/null and b/docs/images/app/en/h5-sessions.webp differ diff --git a/docs/images/app/en/permission-modes.webp b/docs/images/app/en/permission-modes.webp new file mode 100644 index 00000000..791e32fc Binary files /dev/null and b/docs/images/app/en/permission-modes.webp differ diff --git a/docs/images/app/en/pet-desktop.webp b/docs/images/app/en/pet-desktop.webp new file mode 100644 index 00000000..5401e50a Binary files /dev/null and b/docs/images/app/en/pet-desktop.webp differ diff --git a/docs/images/app/en/schedule-create.webp b/docs/images/app/en/schedule-create.webp new file mode 100644 index 00000000..70143b67 Binary files /dev/null and b/docs/images/app/en/schedule-create.webp differ diff --git a/docs/images/app/en/session-dark.webp b/docs/images/app/en/session-dark.webp new file mode 100644 index 00000000..090170d7 Binary files /dev/null and b/docs/images/app/en/session-dark.webp differ diff --git a/docs/images/app/en/session-main.webp b/docs/images/app/en/session-main.webp new file mode 100644 index 00000000..842ca3e5 Binary files /dev/null and b/docs/images/app/en/session-main.webp differ diff --git a/docs/images/app/en/session-new.webp b/docs/images/app/en/session-new.webp new file mode 100644 index 00000000..c48a38ca Binary files /dev/null and b/docs/images/app/en/session-new.webp differ diff --git a/docs/images/app/en/session-permission.webp b/docs/images/app/en/session-permission.webp new file mode 100644 index 00000000..045e4483 Binary files /dev/null and b/docs/images/app/en/session-permission.webp differ diff --git a/docs/images/app/en/settings-agents.webp b/docs/images/app/en/settings-agents.webp new file mode 100644 index 00000000..f827752a Binary files /dev/null and b/docs/images/app/en/settings-agents.webp differ diff --git a/docs/images/app/en/settings-computer-use.webp b/docs/images/app/en/settings-computer-use.webp new file mode 100644 index 00000000..b10a3910 Binary files /dev/null and b/docs/images/app/en/settings-computer-use.webp differ diff --git a/docs/images/app/en/settings-general.webp b/docs/images/app/en/settings-general.webp new file mode 100644 index 00000000..8e834d54 Binary files /dev/null and b/docs/images/app/en/settings-general.webp differ diff --git a/docs/images/app/en/settings-h5.webp b/docs/images/app/en/settings-h5.webp new file mode 100644 index 00000000..56caca86 Binary files /dev/null and b/docs/images/app/en/settings-h5.webp differ diff --git a/docs/images/app/en/settings-im.webp b/docs/images/app/en/settings-im.webp new file mode 100644 index 00000000..d594a766 Binary files /dev/null and b/docs/images/app/en/settings-im.webp differ diff --git a/docs/images/app/en/settings-pets.webp b/docs/images/app/en/settings-pets.webp new file mode 100644 index 00000000..9515fee8 Binary files /dev/null and b/docs/images/app/en/settings-pets.webp differ diff --git a/docs/images/app/en/settings-provider-add.webp b/docs/images/app/en/settings-provider-add.webp new file mode 100644 index 00000000..52ed13af Binary files /dev/null and b/docs/images/app/en/settings-provider-add.webp differ diff --git a/docs/images/app/en/settings-usage.webp b/docs/images/app/en/settings-usage.webp new file mode 100644 index 00000000..66c651e7 Binary files /dev/null and b/docs/images/app/en/settings-usage.webp differ diff --git a/docs/images/app/en/skill-market.webp b/docs/images/app/en/skill-market.webp new file mode 100644 index 00000000..50c03fbd Binary files /dev/null and b/docs/images/app/en/skill-market.webp differ diff --git a/docs/images/app/en/workspace-changes.webp b/docs/images/app/en/workspace-changes.webp new file mode 100644 index 00000000..45a93490 Binary files /dev/null and b/docs/images/app/en/workspace-changes.webp differ diff --git a/docs/images/app/en/workspace-diff.webp b/docs/images/app/en/workspace-diff.webp new file mode 100644 index 00000000..79f69fa8 Binary files /dev/null and b/docs/images/app/en/workspace-diff.webp differ diff --git a/docs/images/app/en/workspace-preview.webp b/docs/images/app/en/workspace-preview.webp new file mode 100644 index 00000000..d55c1f2b Binary files /dev/null and b/docs/images/app/en/workspace-preview.webp differ diff --git a/docs/images/app/h5-session.webp b/docs/images/app/h5-session.webp deleted file mode 100644 index 01e336f9..00000000 Binary files a/docs/images/app/h5-session.webp and /dev/null differ diff --git a/docs/images/app/h5-sessions.webp b/docs/images/app/h5-sessions.webp deleted file mode 100644 index eae52aca..00000000 Binary files a/docs/images/app/h5-sessions.webp and /dev/null differ diff --git a/docs/images/app/permission-modes.webp b/docs/images/app/permission-modes.webp deleted file mode 100644 index 54bf092e..00000000 Binary files a/docs/images/app/permission-modes.webp and /dev/null differ diff --git a/docs/images/app/pet-desktop.webp b/docs/images/app/pet-desktop.webp deleted file mode 100644 index 938d73b8..00000000 Binary files a/docs/images/app/pet-desktop.webp and /dev/null differ diff --git a/docs/images/app/schedule-create.webp b/docs/images/app/schedule-create.webp deleted file mode 100644 index 70be4645..00000000 Binary files a/docs/images/app/schedule-create.webp and /dev/null differ diff --git a/docs/images/app/session-dark.webp b/docs/images/app/session-dark.webp deleted file mode 100644 index ed3d29d7..00000000 Binary files a/docs/images/app/session-dark.webp and /dev/null differ diff --git a/docs/images/app/session-main.webp b/docs/images/app/session-main.webp deleted file mode 100644 index 80fe9152..00000000 Binary files a/docs/images/app/session-main.webp and /dev/null differ diff --git a/docs/images/app/session-new.webp b/docs/images/app/session-new.webp deleted file mode 100644 index d197aa10..00000000 Binary files a/docs/images/app/session-new.webp and /dev/null differ diff --git a/docs/images/app/session-permission.webp b/docs/images/app/session-permission.webp deleted file mode 100644 index 0bc36410..00000000 Binary files a/docs/images/app/session-permission.webp and /dev/null differ diff --git a/docs/images/app/settings-agents.webp b/docs/images/app/settings-agents.webp deleted file mode 100644 index 56d6208d..00000000 Binary files a/docs/images/app/settings-agents.webp and /dev/null differ diff --git a/docs/images/app/settings-computer-use.webp b/docs/images/app/settings-computer-use.webp deleted file mode 100644 index 5a5de494..00000000 Binary files a/docs/images/app/settings-computer-use.webp and /dev/null differ diff --git a/docs/images/app/settings-general.webp b/docs/images/app/settings-general.webp deleted file mode 100644 index db34e396..00000000 Binary files a/docs/images/app/settings-general.webp and /dev/null differ diff --git a/docs/images/app/settings-h5.webp b/docs/images/app/settings-h5.webp deleted file mode 100644 index 31ef2e6e..00000000 Binary files a/docs/images/app/settings-h5.webp and /dev/null differ diff --git a/docs/images/app/settings-im.webp b/docs/images/app/settings-im.webp deleted file mode 100644 index c2b39225..00000000 Binary files a/docs/images/app/settings-im.webp and /dev/null differ diff --git a/docs/images/app/settings-pets.webp b/docs/images/app/settings-pets.webp deleted file mode 100644 index 164fe05d..00000000 Binary files a/docs/images/app/settings-pets.webp and /dev/null differ diff --git a/docs/images/app/settings-provider-add.webp b/docs/images/app/settings-provider-add.webp deleted file mode 100644 index c5265523..00000000 Binary files a/docs/images/app/settings-provider-add.webp and /dev/null differ diff --git a/docs/images/app/settings-usage.webp b/docs/images/app/settings-usage.webp deleted file mode 100644 index 58cadf63..00000000 Binary files a/docs/images/app/settings-usage.webp and /dev/null differ diff --git a/docs/images/app/skill-market.webp b/docs/images/app/skill-market.webp deleted file mode 100644 index 613e845b..00000000 Binary files a/docs/images/app/skill-market.webp and /dev/null differ diff --git a/docs/images/app/workspace-changes.webp b/docs/images/app/workspace-changes.webp deleted file mode 100644 index d1ae348b..00000000 Binary files a/docs/images/app/workspace-changes.webp and /dev/null differ diff --git a/docs/images/app/workspace-diff.webp b/docs/images/app/workspace-diff.webp deleted file mode 100644 index 960e14db..00000000 Binary files a/docs/images/app/workspace-diff.webp and /dev/null differ diff --git a/docs/images/app/workspace-preview.webp b/docs/images/app/workspace-preview.webp deleted file mode 100644 index 4cfb9781..00000000 Binary files a/docs/images/app/workspace-preview.webp and /dev/null differ diff --git a/docs/images/app/zh-CN/agent-create.webp b/docs/images/app/zh-CN/agent-create.webp new file mode 100644 index 00000000..ee848260 Binary files /dev/null and b/docs/images/app/zh-CN/agent-create.webp differ diff --git a/docs/images/app/zh-CN/composer-mention.webp b/docs/images/app/zh-CN/composer-mention.webp new file mode 100644 index 00000000..1dfc312d Binary files /dev/null and b/docs/images/app/zh-CN/composer-mention.webp differ diff --git a/docs/images/app/zh-CN/composer-slash.webp b/docs/images/app/zh-CN/composer-slash.webp new file mode 100644 index 00000000..954f2668 Binary files /dev/null and b/docs/images/app/zh-CN/composer-slash.webp differ diff --git a/docs/images/app/zh-CN/h5-session.webp b/docs/images/app/zh-CN/h5-session.webp new file mode 100644 index 00000000..fc5bac75 Binary files /dev/null and b/docs/images/app/zh-CN/h5-session.webp differ diff --git a/docs/images/app/zh-CN/h5-sessions.webp b/docs/images/app/zh-CN/h5-sessions.webp new file mode 100644 index 00000000..5b85a4b7 Binary files /dev/null and b/docs/images/app/zh-CN/h5-sessions.webp differ diff --git a/docs/images/app/zh-CN/permission-modes.webp b/docs/images/app/zh-CN/permission-modes.webp new file mode 100644 index 00000000..3225fd95 Binary files /dev/null and b/docs/images/app/zh-CN/permission-modes.webp differ diff --git a/docs/images/app/zh-CN/pet-desktop.webp b/docs/images/app/zh-CN/pet-desktop.webp new file mode 100644 index 00000000..19225f4e Binary files /dev/null and b/docs/images/app/zh-CN/pet-desktop.webp differ diff --git a/docs/images/app/zh-CN/schedule-create.webp b/docs/images/app/zh-CN/schedule-create.webp new file mode 100644 index 00000000..86ae8489 Binary files /dev/null and b/docs/images/app/zh-CN/schedule-create.webp differ diff --git a/docs/images/app/zh-CN/session-dark.webp b/docs/images/app/zh-CN/session-dark.webp new file mode 100644 index 00000000..0d3db369 Binary files /dev/null and b/docs/images/app/zh-CN/session-dark.webp differ diff --git a/docs/images/app/zh-CN/session-main.webp b/docs/images/app/zh-CN/session-main.webp new file mode 100644 index 00000000..303660dd Binary files /dev/null and b/docs/images/app/zh-CN/session-main.webp differ diff --git a/docs/images/app/zh-CN/session-new.webp b/docs/images/app/zh-CN/session-new.webp new file mode 100644 index 00000000..619f7cd0 Binary files /dev/null and b/docs/images/app/zh-CN/session-new.webp differ diff --git a/docs/images/app/zh-CN/session-permission.webp b/docs/images/app/zh-CN/session-permission.webp new file mode 100644 index 00000000..7be27129 Binary files /dev/null and b/docs/images/app/zh-CN/session-permission.webp differ diff --git a/docs/images/app/zh-CN/settings-agents.webp b/docs/images/app/zh-CN/settings-agents.webp new file mode 100644 index 00000000..af67792b Binary files /dev/null and b/docs/images/app/zh-CN/settings-agents.webp differ diff --git a/docs/images/app/zh-CN/settings-computer-use.webp b/docs/images/app/zh-CN/settings-computer-use.webp new file mode 100644 index 00000000..28c69cef Binary files /dev/null and b/docs/images/app/zh-CN/settings-computer-use.webp differ diff --git a/docs/images/app/zh-CN/settings-general.webp b/docs/images/app/zh-CN/settings-general.webp new file mode 100644 index 00000000..e1ad8e6b Binary files /dev/null and b/docs/images/app/zh-CN/settings-general.webp differ diff --git a/docs/images/app/zh-CN/settings-h5.webp b/docs/images/app/zh-CN/settings-h5.webp new file mode 100644 index 00000000..212b4781 Binary files /dev/null and b/docs/images/app/zh-CN/settings-h5.webp differ diff --git a/docs/images/app/zh-CN/settings-im.webp b/docs/images/app/zh-CN/settings-im.webp new file mode 100644 index 00000000..4c75b335 Binary files /dev/null and b/docs/images/app/zh-CN/settings-im.webp differ diff --git a/docs/images/app/zh-CN/settings-pets.webp b/docs/images/app/zh-CN/settings-pets.webp new file mode 100644 index 00000000..21f18116 Binary files /dev/null and b/docs/images/app/zh-CN/settings-pets.webp differ diff --git a/docs/images/app/zh-CN/settings-provider-add.webp b/docs/images/app/zh-CN/settings-provider-add.webp new file mode 100644 index 00000000..0be67992 Binary files /dev/null and b/docs/images/app/zh-CN/settings-provider-add.webp differ diff --git a/docs/images/app/zh-CN/settings-usage.webp b/docs/images/app/zh-CN/settings-usage.webp new file mode 100644 index 00000000..660b553a Binary files /dev/null and b/docs/images/app/zh-CN/settings-usage.webp differ diff --git a/docs/images/app/zh-CN/skill-market.webp b/docs/images/app/zh-CN/skill-market.webp new file mode 100644 index 00000000..82559066 Binary files /dev/null and b/docs/images/app/zh-CN/skill-market.webp differ diff --git a/docs/images/app/zh-CN/workspace-changes.webp b/docs/images/app/zh-CN/workspace-changes.webp new file mode 100644 index 00000000..2cb192a1 Binary files /dev/null and b/docs/images/app/zh-CN/workspace-changes.webp differ diff --git a/docs/images/app/zh-CN/workspace-diff.webp b/docs/images/app/zh-CN/workspace-diff.webp new file mode 100644 index 00000000..0b40447d Binary files /dev/null and b/docs/images/app/zh-CN/workspace-diff.webp differ diff --git a/docs/images/app/zh-CN/workspace-preview.webp b/docs/images/app/zh-CN/workspace-preview.webp new file mode 100644 index 00000000..53e9d3d5 Binary files /dev/null and b/docs/images/app/zh-CN/workspace-preview.webp differ diff --git a/docs/start/first-session.md b/docs/start/first-session.md index e66cf763..9379af64 100644 --- a/docs/start/first-session.md +++ b/docs/start/first-session.md @@ -13,7 +13,7 @@ order: 3 点侧边栏的「新建会话」,或按 `Cmd/Ctrl + N`。 -![空会话首屏,底部输入框里有权限模式、运行位置和模型三颗按钮](../images/app/session-new.webp) +![空会话首屏,底部输入框里有权限模式、运行位置和模型三颗按钮](../images/app/zh-CN/session-new.webp) 看输入框底部这一排:`+` 是附件,往右依次是**权限模式**、**运行位置**、**模型 + 推理强度**,最右边是「运行」。 @@ -25,7 +25,7 @@ order: 3 点权限模式按钮,五个档位摊开在你面前。 -![五档权限模式菜单](../images/app/permission-modes.webp) +![五档权限模式菜单](../images/app/zh-CN/permission-modes.webp) | 模式 | App 里的说明 | |---|---| @@ -68,7 +68,7 @@ order: 3 ## 4. 看它干活 -![完整一轮:工具调用折叠卡、思考、权限询问卡、内联 diff](../images/app/session-main.webp) +![完整一轮:工具调用折叠卡、思考、权限询问卡、内联 diff](../images/app/zh-CN/session-main.webp) 它会先摸清情况再动手,你能看到几种不同的卡片: diff --git a/docs/start/index.md b/docs/start/index.md index 53a4e9c6..eb98720d 100644 --- a/docs/start/index.md +++ b/docs/start/index.md @@ -9,7 +9,7 @@ order: 0 它是一个装在你电脑上的应用。你把一个项目文件夹交给它,用大白话说出你想要什么,它去读代码、改文件、跑命令——每一处改动都摆在你眼前,等你点头才算数。 -![一条完整会话:提问、工具调用、编辑文件、内联 diff](../images/app/session-main.webp) +![一条完整会话:提问、工具调用、编辑文件、内联 diff](../images/app/zh-CN/session-main.webp) 上图是一条真实会话:左边是项目和历史,中间是对话,Claude 读完文件后直接改,改了什么就在下面逐行标出来。 diff --git a/docs/start/models.md b/docs/start/models.md index e1397a2e..0f8bbcca 100644 --- a/docs/start/models.md +++ b/docs/start/models.md @@ -67,7 +67,7 @@ Claude Code Haha 自己不带模型,它只是那个替你干活的壳。装完 ## 「添加服务商」弹窗逐个字段 -![添加服务商弹窗:预设、接口地址、认证变量、API 密钥、模型映射](../images/app/settings-provider-add.webp) +![添加服务商弹窗:预设、接口地址、认证变量、API 密钥、模型映射](../images/app/zh-CN/settings-provider-add.webp) **名称**(必填)— 显示在服务商列表里的名字。选了预设会自动填,可以改成你认得出的,比如「DeepSeek-工作号」。 diff --git a/site/scripts/check-docs.mjs b/site/scripts/check-docs.mjs index b05f3c1b..aa75231a 100644 --- a/site/scripts/check-docs.mjs +++ b/site/scripts/check-docs.mjs @@ -2,9 +2,15 @@ import { promises as fs } from 'node:fs' import path from 'node:path' import { generateDocsManifest, paths } from './generate-docs-manifest.mjs' +import { readImageSize } from './image-size.mjs' const markdownTargetPattern = /!?\[[^\]]*]\(([^)\s]+)(?:\s+["'][^"']*["'])?\)/g const htmlTargetPattern = /<(?:a|img)\b[^>]*?\b(?:href|src)=["']([^"']+)["'][^>]*>/gi +const appImagesDirectory = path.join(paths.docsDir, 'images/app') +const appScreenshotDirectories = { + en: 'en', + zh: 'zh-CN' +} function withoutSuffix(target) { return target.split(/[?#]/, 1)[0] @@ -46,6 +52,186 @@ function isImageTarget(target) { return /\.(?:avif|gif|jpe?g|png|svg|webp)$/i.test(withoutSuffix(target)) } +function toPosix(value) { + return value.split(path.sep).join('/') +} + +function resolveLocalTarget(sourceAbsolutePath, target) { + const pathname = decodeURIComponent(withoutSuffix(target)) + + if (!pathname.startsWith('/')) { + return path.resolve(path.dirname(sourceAbsolutePath), pathname) + } + + const repositoryRelative = pathname.replace(/^\/+/, '') + if (repositoryRelative.startsWith('docs/')) { + return path.join(paths.repoDir, repositoryRelative) + } + + const sourceRelative = path.relative(paths.docsDir, sourceAbsolutePath) + const sourceIsDocumentation = sourceRelative !== '' + && sourceRelative !== '..' + && !sourceRelative.startsWith(`..${path.sep}`) + && !path.isAbsolute(sourceRelative) + + return path.join(sourceIsDocumentation ? paths.docsDir : paths.repoDir, repositoryRelative) +} + +function relativeToAppImages(targetPath) { + const relativePath = path.relative(appImagesDirectory, targetPath) + const outsideDirectory = relativePath === '' + || relativePath === '..' + || relativePath.startsWith(`..${path.sep}`) + || path.isAbsolute(relativePath) + + return outsideDirectory ? null : toPosix(relativePath) +} + +async function checkReadmeImages(readmes) { + const problems = [] + + for (const readme of readmes) { + for (const target of collectTargets(readme.content)) { + if (!target || isExternal(target) || !isImageTarget(target)) { + continue + } + + const resolvedFile = resolveLocalTarget(readme.absolutePath, target) + if (!await exists(resolvedFile)) { + problems.push(`${readme.sourcePath}: unresolved image ${target}`) + } + } + } + + return problems +} + +function checkAppScreenshotReferences(sources) { + const problems = [] + + for (const source of sources) { + const expectedDirectory = appScreenshotDirectories[source.locale] + + for (const target of collectTargets(source.content)) { + if (!target || isExternal(target) || !isImageTarget(target)) { + continue + } + + const resolvedFile = resolveLocalTarget(source.absolutePath, target) + const appRelativePath = relativeToAppImages(resolvedFile) + if (!appRelativePath) { + continue + } + + if (!appRelativePath.includes('/')) { + problems.push( + `${source.sourcePath}: legacy app screenshot path ${target}; use docs/images/app/${expectedDirectory}/...` + ) + continue + } + + if (!appRelativePath.startsWith(`${expectedDirectory}/`)) { + problems.push( + `${source.sourcePath}: app screenshot ${target} must use docs/images/app/${expectedDirectory}/` + ) + } + } + } + + return problems +} + +async function collectAppScreenshots(locale, problems) { + const directoryName = appScreenshotDirectories[locale] + const directory = path.join(appImagesDirectory, directoryName) + let entries + + try { + entries = await fs.readdir(directory, { withFileTypes: true }) + } catch { + problems.push(`docs/images/app/${directoryName}: screenshot directory is missing`) + return new Map() + } + + const screenshots = new Map() + for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) { + if (!entry.isFile() || path.extname(entry.name).toLowerCase() !== '.webp') { + continue + } + + const basename = path.basename(entry.name, path.extname(entry.name)) + if (screenshots.has(basename)) { + problems.push(`docs/images/app/${directoryName}: duplicate screenshot basename ${basename}`) + continue + } + + screenshots.set(basename, path.join(directory, entry.name)) + } + + if (screenshots.size === 0) { + problems.push(`docs/images/app/${directoryName}: no WebP screenshots found`) + } + + return screenshots +} + +async function checkAppScreenshotFiles() { + const problems = [] + const english = await collectAppScreenshots('en', problems) + const chinese = await collectAppScreenshots('zh', problems) + + for (const basename of english.keys()) { + if (!chinese.has(basename)) { + problems.push(`docs/images/app/zh-CN: missing ${basename}.webp`) + } + } + for (const basename of chinese.keys()) { + if (!english.has(basename)) { + problems.push(`docs/images/app/en: missing ${basename}.webp`) + } + } + + const sizes = { en: new Map(), zh: new Map() } + for (const [locale, screenshots] of Object.entries({ en: english, zh: chinese })) { + const directoryName = appScreenshotDirectories[locale] + + for (const [basename, screenshotPath] of screenshots) { + const size = await readImageSize(screenshotPath) + if (!size) { + problems.push(`docs/images/app/${directoryName}/${basename}.webp: unreadable image dimensions`) + continue + } + + sizes[locale].set(basename, size) + const expectedWidth = basename.startsWith('h5-') ? 1206 : 2000 + if (size.width !== expectedWidth) { + problems.push( + `docs/images/app/${directoryName}/${basename}.webp: width ${size.width}, expected ${expectedWidth}` + ) + } + } + } + + let checkedPairs = 0 + for (const basename of english.keys()) { + const englishSize = sizes.en.get(basename) + const chineseSize = sizes.zh.get(basename) + if (!englishSize || !chineseSize) { + continue + } + + checkedPairs += 1 + if (englishSize.width !== chineseSize.width || englishSize.height !== chineseSize.height) { + problems.push( + `docs/images/app/${basename}.webp: en is ${englishSize.width}x${englishSize.height}, ` + + `zh-CN is ${chineseSize.width}x${chineseSize.height}` + ) + } + } + + return { checkedPairs, problems } +} + /** * 语言分流的判定规则在两处各有一份:src/lib/locale.js(可测的模块)和 index.html 里的内联 * 副本(首帧就要跳,等不到模块加载)。两处漂移不会报错,只会让首页悄悄按旧规则分流,所以 @@ -82,6 +268,17 @@ async function checkLocaleRedirect() { async function main() { const { records } = await generateDocsManifest() + const readmes = await Promise.all([ + { locale: 'en', sourcePath: 'README.md' }, + { locale: 'zh', sourcePath: 'README.zh-CN.md' } + ].map(async (readme) => { + const absolutePath = path.join(paths.repoDir, readme.sourcePath) + return { + ...readme, + absolutePath, + content: await fs.readFile(absolutePath, 'utf8') + } + })) const routes = new Set([ '/', '/docs', @@ -90,6 +287,18 @@ async function main() { ...records.map((record) => record.path), ]) const problems = [...await checkLocaleRedirect()] + problems.push(...await checkReadmeImages(readmes)) + problems.push(...checkAppScreenshotReferences([ + ...readmes, + ...records.map((record) => ({ + absolutePath: path.join(paths.repoDir, record.sourcePath), + content: record.content, + locale: record.locale, + sourcePath: record.sourcePath + })) + ])) + const screenshotCheck = await checkAppScreenshotFiles() + problems.push(...screenshotCheck.problems) let checkedTargets = 0 for (const record of records) { @@ -141,7 +350,10 @@ async function main() { return } - console.log(`Documentation check passed: ${records.length} pages, ${checkedTargets} local links and images.`) + console.log( + `Documentation check passed: ${records.length} pages, ${checkedTargets} local links and images, ` + + `${screenshotCheck.checkedPairs} bilingual app screenshot pairs.` + ) } await main() diff --git a/site/src/pages/home/content.js b/site/src/pages/home/content.js index 87ee3e33..e5fa208b 100644 --- a/site/src/pages/home/content.js +++ b/site/src/pages/home/content.js @@ -1,11 +1,19 @@ -import sessionMain from '../../../../docs/images/app/session-main.webp' -import workspaceDiff from '../../../../docs/images/app/workspace-diff.webp' -import workspacePreview from '../../../../docs/images/app/workspace-preview.webp' -import providerAdd from '../../../../docs/images/app/settings-provider-add.webp' -import skillMarket from '../../../../docs/images/app/skill-market.webp' -import scheduleCreate from '../../../../docs/images/app/schedule-create.webp' -import h5Session from '../../../../docs/images/app/h5-session.webp' -import petDesktop from '../../../../docs/images/app/pet-desktop.webp' +import sessionMainZh from '../../../../docs/images/app/zh-CN/session-main.webp' +import workspaceDiffZh from '../../../../docs/images/app/zh-CN/workspace-diff.webp' +import workspacePreviewZh from '../../../../docs/images/app/zh-CN/workspace-preview.webp' +import providerAddZh from '../../../../docs/images/app/zh-CN/settings-provider-add.webp' +import skillMarketZh from '../../../../docs/images/app/zh-CN/skill-market.webp' +import scheduleCreateZh from '../../../../docs/images/app/zh-CN/schedule-create.webp' +import h5SessionZh from '../../../../docs/images/app/zh-CN/h5-session.webp' +import petDesktopZh from '../../../../docs/images/app/zh-CN/pet-desktop.webp' +import sessionMainEn from '../../../../docs/images/app/en/session-main.webp' +import workspaceDiffEn from '../../../../docs/images/app/en/workspace-diff.webp' +import workspacePreviewEn from '../../../../docs/images/app/en/workspace-preview.webp' +import providerAddEn from '../../../../docs/images/app/en/settings-provider-add.webp' +import skillMarketEn from '../../../../docs/images/app/en/skill-market.webp' +import scheduleCreateEn from '../../../../docs/images/app/en/schedule-create.webp' +import h5SessionEn from '../../../../docs/images/app/en/h5-session.webp' +import petDesktopEn from '../../../../docs/images/app/en/pet-desktop.webp' // 吉祥物与截图一样从 docs/ 取 —— docs/ 是站点唯一的媒体源。 // 原图是桌面端的 agent-mascots,改动那边时记得同步这四张。 @@ -14,17 +22,31 @@ import huhu from '../../../../docs/images/mascots/huhu.png' import bubu from '../../../../docs/images/mascots/bubu.png' import huihui from '../../../../docs/images/mascots/huihui.png' -export const images = { - h5Session, - petDesktop, - providerAdd, - scheduleCreate, - sessionMain, - skillMarket, - workspaceDiff, - workspacePreview +const localizedImages = { + zh: { + h5Session: h5SessionZh, + petDesktop: petDesktopZh, + providerAdd: providerAddZh, + scheduleCreate: scheduleCreateZh, + sessionMain: sessionMainZh, + skillMarket: skillMarketZh, + workspaceDiff: workspaceDiffZh, + workspacePreview: workspacePreviewZh + }, + en: { + h5Session: h5SessionEn, + petDesktop: petDesktopEn, + providerAdd: providerAddEn, + scheduleCreate: scheduleCreateEn, + sessionMain: sessionMainEn, + skillMarket: skillMarketEn, + workspaceDiff: workspaceDiffEn, + workspacePreview: workspacePreviewEn + } } +export const images = localizedImages.zh + export const content = { zh: { hero: { @@ -58,49 +80,49 @@ export const content = { label: '会话', title: '说一句话,看它一步步做完', body: '选好项目、权限模式和模型就能开工。它读了哪些文件、执行了什么命令、改了哪一行,全都留在对话里。', - image: sessionMain + image: localizedImages.zh.sessionMain }, { id: 'review', label: '审阅', title: '改了什么,逐个文件看清楚', body: '右侧工作区列出本轮改动,点开就是带语法高亮的 Diff。看不顺眼可以撤销整轮。', - image: workspaceDiff + image: localizedImages.zh.workspaceDiff }, { id: 'preview', label: '预览', title: '页面效果,会话里直接验证', body: '内置浏览器打开本地服务,改完当场看效果;截图和元素选择都能带回对话继续说。', - image: workspacePreview + image: localizedImages.zh.workspacePreview }, { id: 'models', label: '模型', title: '接哪个模型,你自己定', body: 'Claude / ChatGPT / Grok 官方账号直接登录,也可以接 DeepSeek、Kimi、智谱、MiniMax,或者本地跑的 LM Studio 与 Ollama。', - image: providerAdd + image: localizedImages.zh.providerAdd }, { id: 'skills', label: '技能', title: '缺什么手艺,装什么手艺', body: '技能市场聚合 ClawHub 与 SkillHub,每个技能都标了来源和安全状态,装之前先看清楚。', - image: skillMarket + image: localizedImages.zh.skillMarket }, { id: 'schedule', label: '定时', title: '设好时间,它按时回来交活', body: '定好频率、模型、目录和通知方式;任务在独立会话里执行,每跑一次都有记录可查。', - image: scheduleCreate + image: localizedImages.zh.scheduleCreate }, { id: 'remote', label: '手机', title: '离开电脑,会话不断', body: '扫码用手机浏览器接着聊。锁屏切后台也不会打断正在跑的任务,回来就能看结果。', - image: h5Session + image: localizedImages.zh.h5Session } ] }, @@ -188,13 +210,13 @@ export const content = { title: 'Every screenshot is v0.5.0. No concept art.', lede: 'What you see is what opens after install.', tabs: [ - { id: 'session', label: 'Session', title: 'Say it once. Watch it get done.', body: 'Pick a project, a permission mode and a model. Every file it read, every command it ran and every line it changed stays in the thread.', image: sessionMain }, - { id: 'review', label: 'Review', title: 'Know exactly what changed', body: 'The workspace lists this turn’s edits; open any file for a syntax-highlighted diff. Don’t like it? Undo the whole turn.', image: workspaceDiff }, - { id: 'preview', label: 'Preview', title: 'Check the page without leaving', body: 'Open your dev server in the built-in browser, see the result immediately, and bring screenshots or picked elements back into the thread.', image: workspacePreview }, - { id: 'models', label: 'Models', title: 'Bring your own model', body: 'Sign in to Claude, ChatGPT or Grok, or point it at DeepSeek, Kimi, Zhipu, MiniMax — or LM Studio and Ollama running on your own machine.', image: providerAdd }, - { id: 'skills', label: 'Skills', title: 'Missing a trick? Install it.', body: 'The marketplace aggregates ClawHub and SkillHub, and labels every skill with its source and safety status before you install.', image: skillMarket }, - { id: 'schedule', label: 'Schedule', title: 'Set the time. It comes back with results.', body: 'Choose a cadence, model, directory and notification. Jobs run in their own sessions and every run leaves a record.', image: scheduleCreate }, - { id: 'remote', label: 'Mobile', title: 'Step away, keep the session', body: 'Scan the QR code and continue in your phone browser. Locking the screen won’t kill a running task.', image: h5Session } + { id: 'session', label: 'Session', title: 'Say it once. Watch it get done.', body: 'Pick a project, a permission mode and a model. Every file it read, every command it ran and every line it changed stays in the thread.', image: localizedImages.en.sessionMain }, + { id: 'review', label: 'Review', title: 'Know exactly what changed', body: 'The workspace lists this turn’s edits; open any file for a syntax-highlighted diff. Don’t like it? Undo the whole turn.', image: localizedImages.en.workspaceDiff }, + { id: 'preview', label: 'Preview', title: 'Check the page without leaving', body: 'Open your dev server in the built-in browser, see the result immediately, and bring screenshots or picked elements back into the thread.', image: localizedImages.en.workspacePreview }, + { id: 'models', label: 'Models', title: 'Bring your own model', body: 'Sign in to Claude, ChatGPT or Grok, or point it at DeepSeek, Kimi, Zhipu, MiniMax — or LM Studio and Ollama running on your own machine.', image: localizedImages.en.providerAdd }, + { id: 'skills', label: 'Skills', title: 'Missing a trick? Install it.', body: 'The marketplace aggregates ClawHub and SkillHub, and labels every skill with its source and safety status before you install.', image: localizedImages.en.skillMarket }, + { id: 'schedule', label: 'Schedule', title: 'Set the time. It comes back with results.', body: 'Choose a cadence, model, directory and notification. Jobs run in their own sessions and every run leaves a record.', image: localizedImages.en.scheduleCreate }, + { id: 'remote', label: 'Mobile', title: 'Step away, keep the session', body: 'Scan the QR code and continue in your phone browser. Locking the screen won’t kill a running task.', image: localizedImages.en.h5Session } ] }, crew: {