<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Codex on KnightLi的博客</title>
        <link>https://knightli.com/tags/codex/</link>
        <description>Recent content in Codex on KnightLi的博客</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <lastBuildDate>Sun, 07 Jun 2026 09:07:27 +0800</lastBuildDate><atom:link href="https://knightli.com/tags/codex/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Understand Anything 详细使用指南：安装、命令、Dashboard 与知识图谱工作流</title>
        <link>https://knightli.com/2026/06/07/understand-anything-codebase-knowledge-graph/</link>
        <pubDate>Sun, 07 Jun 2026 09:07:27 +0800</pubDate>
        
        <guid>https://knightli.com/2026/06/07/understand-anything-codebase-knowledge-graph/</guid>
        <description>&lt;p&gt;&lt;code&gt;Lum1104/Understand-Anything&lt;/code&gt; 是一个面向代码理解的开源工具。它可以把代码库、知识库或文档分析成可交互的知识图谱，让你在 Dashboard 中搜索、浏览节点，并围绕项目结构继续提问。&lt;/p&gt;
&lt;p&gt;如果你刚接手一个大型项目，最难的往往不是“没有代码”，而是不知道从哪里开始读。Understand Anything 的思路是先扫描项目，提取文件、函数、类、依赖和业务域关系，再生成可视化图谱，帮助你从全局结构进入细节。&lt;/p&gt;
&lt;h2 id=&#34;适合先解决什么问题&#34;&gt;适合先解决什么问题
&lt;/h2&gt;&lt;p&gt;它比较适合下面几类场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;快速理解陌生代码库的模块结构；&lt;/li&gt;
&lt;li&gt;给新成员生成 onboarding 导览；&lt;/li&gt;
&lt;li&gt;在重构前查看依赖和影响范围；&lt;/li&gt;
&lt;li&gt;在代码评审前理解改动波及面；&lt;/li&gt;
&lt;li&gt;把团队知识库或项目文档转成可探索的关系图；&lt;/li&gt;
&lt;li&gt;给 Codex、Claude Code、Cursor、Copilot 等 AI 编程环境补充项目上下文。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于中大型项目，它更像一张“项目地图”：不是替你做最终判断，而是帮你更快找到入口。&lt;/p&gt;
&lt;h2 id=&#34;安装方式&#34;&gt;安装方式
&lt;/h2&gt;&lt;p&gt;在 Claude Code 中，可以直接通过插件市场安装：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/plugin marketplace add Lum1104/Understand-Anything
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/plugin install understand-anything
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;它也支持 Codex、Cursor、VS Code + GitHub Copilot、Copilot CLI、Gemini CLI、OpenCode、OpenClaw、Antigravity、Vibe CLI、Trae 等平台。&lt;/p&gt;
&lt;p&gt;macOS / Linux 可以使用安装脚本：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -fsSL https://raw.githubusercontent.com/Lum1104/Understand-Anything/main/install.sh &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果要直接安装到 Codex：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -fsSL https://raw.githubusercontent.com/Lum1104/Understand-Anything/main/install.sh &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bash -s codex
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Windows PowerShell：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;iwr &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-useb&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;https&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;//&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;raw&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;githubusercontent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;com&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Lum1104&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Understand-Anything&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;install&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;ps1&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;iex
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;安装脚本会把仓库克隆到：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;~/.understand-anything/repo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;并为对应平台创建必要链接。安装完成后，通常需要重启 CLI 或 IDE。&lt;/p&gt;
&lt;h2 id=&#34;第一次分析代码库&#34;&gt;第一次分析代码库
&lt;/h2&gt;&lt;p&gt;进入目标项目目录后，运行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;它会扫描项目，提取文件、函数、类和依赖关系，并生成知识图谱文件：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.understand-anything/knowledge-graph.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果你希望生成中文节点说明和中文 Dashboard UI，可以指定语言：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand --language zh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;项目也支持其他语言选项，例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;en
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;zh
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;zh-TW
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ja
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ko
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ru
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;第一次运行时，如果没有显式指定 &lt;code&gt;--language&lt;/code&gt;，工具会根据当前对话语言进行检测，并在需要时询问确认。选择会保存到：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.understand-anything/config.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;后续运行会复用这个配置。&lt;/p&gt;
&lt;h2 id=&#34;先分析哪些目录&#34;&gt;先分析哪些目录
&lt;/h2&gt;&lt;p&gt;如果项目是 monorepo，第一次不一定要直接分析整个仓库。更稳妥的方式是先从关键目录试跑，观察耗时和图谱质量。&lt;/p&gt;
&lt;p&gt;可以优先选择这些目录：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/&lt;/code&gt;：多数单体应用的核心业务代码；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;apps/&lt;/code&gt;：monorepo 中的前端、后端或独立应用入口；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;packages/&lt;/code&gt;：共享库、SDK、组件库或基础模块；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;services/&lt;/code&gt;：微服务项目中的服务目录；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backend/&lt;/code&gt;、&lt;code&gt;frontend/&lt;/code&gt;：前后端分离项目的主要边界；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docs/&lt;/code&gt; 或 &lt;code&gt;wiki/&lt;/code&gt;：需要分析知识库时再单独处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如只分析前端应用目录：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand apps/web
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;或者只分析共享包：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand packages/core
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这样可以避免第一次就扫描完整 monorepo，尤其适合依赖复杂、历史包很多、生成结果可能很大的项目。&lt;/p&gt;
&lt;h2 id=&#34;打开-dashboard&#34;&gt;打开 Dashboard
&lt;/h2&gt;&lt;p&gt;生成图谱后，运行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-dashboard
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Dashboard 会打开一个交互式页面，你可以在里面：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;平移和缩放项目知识图谱；&lt;/li&gt;
&lt;li&gt;搜索文件、函数、类或语义相关内容；&lt;/li&gt;
&lt;li&gt;点击节点查看摘要、关系和代码；&lt;/li&gt;
&lt;li&gt;按架构层级查看 API、Service、Data、UI、Utility 等分组；&lt;/li&gt;
&lt;li&gt;跟随自动生成的导览理解项目结构。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;读陌生项目时，可以先从 Dashboard 的搜索入口开始。例如先搜 &lt;code&gt;auth&lt;/code&gt;、&lt;code&gt;payment&lt;/code&gt;、&lt;code&gt;api&lt;/code&gt;、&lt;code&gt;database&lt;/code&gt;、&lt;code&gt;router&lt;/code&gt;，再沿着节点关系继续展开。&lt;/p&gt;
&lt;h2 id=&#34;常用命令&#34;&gt;常用命令
&lt;/h2&gt;&lt;p&gt;除了 &lt;code&gt;/understand&lt;/code&gt; 和 &lt;code&gt;/understand-dashboard&lt;/code&gt;，比较常用的命令还有：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-chat How does the payment flow work?
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-diff
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-explain src/auth/login.ts
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-onboard
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-domain
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-knowledge ~/path/to/wiki
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这些命令大致对应几类任务：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/understand-chat&lt;/code&gt;：围绕代码库提问；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/understand-diff&lt;/code&gt;：分析当前改动影响哪些系统部分；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/understand-explain&lt;/code&gt;：深入解释某个文件或函数；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/understand-onboard&lt;/code&gt;：生成新成员导览；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/understand-domain&lt;/code&gt;：提取业务域、流程和步骤；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/understand-knowledge&lt;/code&gt;：分析知识库或 wiki。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果是第一次用，建议顺序是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-dashboard
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-onboard
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-chat 这个项目的核心模块有哪些？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这样可以先建立全局视图，再进入具体问题。&lt;/p&gt;
&lt;h2 id=&#34;常见工作流&#34;&gt;常见工作流
&lt;/h2&gt;&lt;h3 id=&#34;快速接手陌生项目&#34;&gt;快速接手陌生项目
&lt;/h3&gt;&lt;p&gt;先在项目根目录运行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand --language zh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后打开 Dashboard：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-dashboard
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;先看架构层级和依赖关系，再运行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-onboard
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这条路线适合新成员入门，也适合你临时接手一个维护任务。&lt;/p&gt;
&lt;h3 id=&#34;解释关键文件&#34;&gt;解释关键文件
&lt;/h3&gt;&lt;p&gt;如果你已经知道某个文件很重要，但看不懂它在系统里的位置，可以运行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-explain src/auth/login.ts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后结合 Dashboard 查看它连接到哪些模块。这样比只读单个文件更容易理解上下游关系。&lt;/p&gt;
&lt;h3 id=&#34;提交前做影响分析&#34;&gt;提交前做影响分析
&lt;/h3&gt;&lt;p&gt;改完代码后，先运行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/understand-diff
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;它可以帮助你判断当前改动可能影响哪些模块。这个结果不能替代测试，但适合在提交前做一次结构层面的自查。&lt;/p&gt;
&lt;h3 id=&#34;给团队共享项目地图&#34;&gt;给团队共享项目地图
&lt;/h3&gt;&lt;p&gt;Understand Anything 生成的图谱本质上是 JSON。团队可以考虑提交必要的 &lt;code&gt;.understand-anything/&lt;/code&gt; 文件，让其他成员跳过首次分析流程。&lt;/p&gt;
&lt;p&gt;适合提交的通常是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.understand-anything/knowledge-graph.json
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.understand-anything/config.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;不建议提交的是本地中间文件和临时分析结果：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.understand-anything/intermediate/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.understand-anything/diff-overlay.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果生成的图谱很大，可以配合 Git LFS：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git lfs install
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git lfs track &lt;span class=&#34;s2&#34;&gt;&amp;#34;.understand-anything/*.json&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git add .gitattributes .understand-anything/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;团队共享图谱时还要注意两点：第一，图谱会随代码变化过期，需要有人维护更新；第二，图谱里可能包含文件路径、函数名、业务描述和部分语义摘要，私有项目提交前要确认是否适合进入仓库。&lt;/p&gt;
&lt;h2 id=&#34;和传统架构文档有什么区别&#34;&gt;和传统架构文档有什么区别
&lt;/h2&gt;&lt;p&gt;传统架构文档通常是静态的，优点是表达清楚、适合沉淀决策背景；缺点是很容易和代码实现脱节。项目迭代几个月后，文档里的模块边界、调用关系和真实代码可能已经不一致。&lt;/p&gt;
&lt;p&gt;Understand Anything 更像自动生成的项目理解层。它从代码和文档中抽取结构关系，再通过知识图谱展示出来。它的优势是能跟随项目重新生成，适合快速建立当前视图；缺点是解释内容仍需要人工复核，不能替代架构师写下来的设计取舍、历史背景和团队约定。&lt;/p&gt;
&lt;p&gt;更实用的组合是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用传统架构文档记录目标设计、约束、决策和演进背景；&lt;/li&gt;
&lt;li&gt;用 Understand Anything 生成当前代码结构、依赖关系和可搜索图谱；&lt;/li&gt;
&lt;li&gt;当两者不一致时，把差异当作一次文档或架构债务检查。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;和-sourcegraphdeepwikicursor-怎么区分&#34;&gt;和 Sourcegraph、DeepWiki、Cursor 怎么区分
&lt;/h2&gt;&lt;p&gt;这些工具都能帮助理解代码，但适合的入口不同。&lt;/p&gt;
&lt;p&gt;Sourcegraph 更偏代码搜索、跨仓库跳转和符号级检索，适合在大量仓库中快速定位实现。DeepWiki 更偏把仓库变成可阅读的自动化文档，适合先获得文档化概览。Cursor 的项目理解能力更贴近编辑器内编码体验，适合边写边问、边改边补上下文。&lt;/p&gt;
&lt;p&gt;Understand Anything 的特点是把代码库显式转成知识图谱，并提供 Dashboard、导览、影响分析和知识库分析。它适合你想“先看项目地图，再进入代码细节”的场景。&lt;/p&gt;
&lt;p&gt;简单说：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;想跨仓库搜索代码：优先看 Sourcegraph；&lt;/li&gt;
&lt;li&gt;想快速读自动生成的项目文档：可以看 DeepWiki；&lt;/li&gt;
&lt;li&gt;想在编辑器里边写边问：Cursor 更顺手；&lt;/li&gt;
&lt;li&gt;想把代码结构、依赖和业务关系变成图谱：Understand Anything 更贴合。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这不是硬评测，更多是入口差异。实际工作里可以组合使用。&lt;/p&gt;
&lt;h2 id=&#34;隐私与私有仓库风险&#34;&gt;隐私与私有仓库风险
&lt;/h2&gt;&lt;p&gt;对私有代码库使用这类工具前，先确认所接入 AI 平台的数据策略。需要重点看：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;代码片段、文件路径、函数名是否会发送到外部模型；&lt;/li&gt;
&lt;li&gt;生成的摘要和图谱是否包含敏感业务信息；&lt;/li&gt;
&lt;li&gt;企业账号、团队账号和个人账号的数据保留策略是否不同；&lt;/li&gt;
&lt;li&gt;是否允许在当前项目中使用外部 LLM；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.understand-anything/&lt;/code&gt; 生成文件是否会被提交到远端仓库。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果项目涉及客户数据、商业机密、未公开产品逻辑或合规要求，建议先在脱敏样例、开源项目或内部允许的目录上试用，再决定是否接入真实私有仓库。&lt;/p&gt;
&lt;h2 id=&#34;什么时候不适合用&#34;&gt;什么时候不适合用
&lt;/h2&gt;&lt;p&gt;Understand Anything 不是所有项目都需要。下面几种情况可以先不引入：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;项目很小，直接读代码比生成图谱更快；&lt;/li&gt;
&lt;li&gt;代码结构非常混乱，而且缺少命名、模块和文档线索，生成结果可能难以解释；&lt;/li&gt;
&lt;li&gt;团队没人维护图谱，生成一次后长期不更新；&lt;/li&gt;
&lt;li&gt;你只需要查一个函数或一个报错，不需要全局项目地图；&lt;/li&gt;
&lt;li&gt;私有仓库的安全策略不允许把代码上下文发送给外部 AI 服务；&lt;/li&gt;
&lt;li&gt;当前任务已经有清晰入口，引入额外工具反而增加流程成本。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;比较稳妥的做法是先在关键目录试跑，确认图谱质量、耗时和隐私边界后，再决定是否分析整个仓库。&lt;/p&gt;
&lt;h2 id=&#34;背后的实现思路&#34;&gt;背后的实现思路
&lt;/h2&gt;&lt;p&gt;Understand Anything 采用 Tree-sitter 与 LLM 结合的方式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tree-sitter 负责确定性结构分析，例如 import/export、函数、类、调用点、继承关系；&lt;/li&gt;
&lt;li&gt;LLM 负责语义层内容，例如自然语言摘要、标签、架构分层、业务域映射、导览说明；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/understand&lt;/code&gt; 会编排多个 agent，包括项目扫描、文件分析、架构分析、导览生成和图谱校验；&lt;/li&gt;
&lt;li&gt;增量更新只重新分析发生变化的文件，适合持续维护知识图谱。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这种组合能减少“纯靠 LLM 猜项目结构”的问题，同时保留自然语言解释带来的可读性。&lt;/p&gt;
&lt;h2 id=&#34;使用边界&#34;&gt;使用边界
&lt;/h2&gt;&lt;p&gt;这类工具适合辅助理解，但不应该替代工程判断：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;图谱质量取决于项目结构、语言支持和解析结果；&lt;/li&gt;
&lt;li&gt;LLM 生成的业务解释需要人工复核；&lt;/li&gt;
&lt;li&gt;大型仓库第一次分析可能需要较长时间；&lt;/li&gt;
&lt;li&gt;对私有代码库使用前，要确认所接入 AI 平台的数据与隐私策略；&lt;/li&gt;
&lt;li&gt;小型项目未必需要完整图谱，直接读代码可能更快。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;Understand Anything 的价值在于把“读代码”变成“探索项目地图”。安装后先运行 &lt;code&gt;/understand&lt;/code&gt; 生成图谱，再用 &lt;code&gt;/understand-dashboard&lt;/code&gt; 浏览结构，配合 &lt;code&gt;/understand-chat&lt;/code&gt;、&lt;code&gt;/understand-diff&lt;/code&gt;、&lt;code&gt;/understand-explain&lt;/code&gt; 处理具体问题。&lt;/p&gt;
&lt;p&gt;如果你经常接触陌生代码库、维护大型项目，或者需要给团队做 onboarding，它值得试用。尤其是在 Codex、Claude Code、Cursor、Copilot 等 AI 编程环境里，这类知识图谱工具可能会成为代码理解工作流的一部分。&lt;/p&gt;
&lt;h2 id=&#34;参考来源&#34;&gt;参考来源
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/Lum1104/Understand-Anything&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Lum1104/Understand-Anything - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Taste Skill 怎么用？给 AI 前端生成加一点审美约束</title>
        <link>https://knightli.com/2026/06/06/taste-skill-ai-frontend-design/</link>
        <pubDate>Sat, 06 Jun 2026 22:22:56 +0800</pubDate>
        
        <guid>https://knightli.com/2026/06/06/taste-skill-ai-frontend-design/</guid>
        <description>&lt;p&gt;&lt;code&gt;Leonxlnx/taste-skill&lt;/code&gt; 是一个很有意思的前端 Agent Skill 项目。它的目标不是再做一个 UI 组件库，而是给 Codex、Cursor、Claude Code 这类 AI 编程工具加一套“审美约束”，减少那种一眼 AI 味的模板界面。&lt;/p&gt;
&lt;p&gt;项目 README 里把它叫做 Anti-Slop Frontend Framework。这个说法有点夸张，但方向很准：AI 写前端最大的问题，经常不是不会写代码，而是默认布局太平、层级太弱、间距像自动生成、动效和字体都没有判断。&lt;/p&gt;
&lt;h2 id=&#34;它到底是什么&#34;&gt;它到底是什么
&lt;/h2&gt;&lt;p&gt;Taste Skill 本质上是一组可安装、可复制、可粘贴的 Agent Skills。它们不是运行时依赖，也不是浏览器插件，而是给 AI Agent 的工作规则。&lt;/p&gt;
&lt;p&gt;它会要求模型在生成前端时更关注：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;layout：布局不要只会居中卡片；&lt;/li&gt;
&lt;li&gt;typography：字号、字重、行高要有层级；&lt;/li&gt;
&lt;li&gt;spacing：留白、边距、密度要符合场景；&lt;/li&gt;
&lt;li&gt;motion：动效要服务交互，不是随便加动画；&lt;/li&gt;
&lt;li&gt;design language：根据产品类型推断设计语言；&lt;/li&gt;
&lt;li&gt;anti-slop：避免模板感、占位符和半成品输出。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这类 skill 的价值不在于“多写几句 prompt”，而是把一些前端审美判断固定成可复用规则，让不同项目里都能调用。&lt;/p&gt;
&lt;h2 id=&#34;怎么安装&#34;&gt;怎么安装
&lt;/h2&gt;&lt;p&gt;README 推荐用 &lt;code&gt;npx skills add&lt;/code&gt; 安装：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npx skills add https://github.com/Leonxlnx/taste-skill
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果只安装默认前端设计 skill，可以指定：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npx skills add https://github.com/Leonxlnx/taste-skill --skill &lt;span class=&#34;s2&#34;&gt;&amp;#34;design-taste-frontend&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果你依赖旧版行为，也可以安装 v1：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npx skills add https://github.com/Leonxlnx/taste-skill --skill &lt;span class=&#34;s2&#34;&gt;&amp;#34;design-taste-frontend-v1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;项目也说明，可以直接复制任意 &lt;code&gt;SKILL.md&lt;/code&gt; 到项目里，或者把内容粘贴到 ChatGPT / Codex 对话中使用。也就是说，它不是必须绑定某个具体平台。&lt;/p&gt;
&lt;h2 id=&#34;内置哪些-skill&#34;&gt;内置哪些 Skill
&lt;/h2&gt;&lt;p&gt;Taste Skill 不是只有一个文件。README 里列了多种 skill：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Skill&lt;/th&gt;
          &lt;th&gt;Install name&lt;/th&gt;
          &lt;th&gt;用途&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;taste-skill&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;design-taste-frontend&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;默认前端审美规则，当前 v2 仍在实验迭代&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;taste-skill-v1&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;design-taste-frontend-v1&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;保留旧版行为&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;gpt-tasteskill&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;gpt-taste&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;更适合 GPT / Codex 的严格版本&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;image-to-code-skill&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;image-to-code&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;先生成参考图，再分析，再写代码&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;redesign-skill&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;redesign-existing-projects&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;先审计已有项目，再改 UI&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;soft-skill&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;high-end-visual-design&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;偏高级、柔和、留白充足的视觉方向&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;minimalist-skill&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;minimalist-ui&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;偏 Notion / Linear 风格的克制产品 UI&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;brutalist-skill&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;industrial-brutalist-ui&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;偏工业、瑞士字体、强对比的实验风格&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;output-skill&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;full-output-enforcement&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;用来压制半截输出和占位符&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;另外还有 image generation skills，用来生成网页、移动端和品牌板参考图。它们不直接输出代码，而是产出视觉参考，再交给 Codex、Cursor 或 Claude Code 实现。&lt;/p&gt;
&lt;h2 id=&#34;适合怎么用&#34;&gt;适合怎么用
&lt;/h2&gt;&lt;p&gt;如果你只是让 AI 写一个后台表单，直接说清楚需求也许就够了。但如果你要做：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;产品官网；&lt;/li&gt;
&lt;li&gt;SaaS Dashboard；&lt;/li&gt;
&lt;li&gt;移动端页面；&lt;/li&gt;
&lt;li&gt;品牌落地页；&lt;/li&gt;
&lt;li&gt;作品集；&lt;/li&gt;
&lt;li&gt;高级感工具界面；&lt;/li&gt;
&lt;li&gt;已有项目 UI 重设计；&lt;/li&gt;
&lt;li&gt;从参考图还原前端。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;那 Taste Skill 会更有用。它帮你提前约束“这应该是什么气质的界面”，而不是等 AI 生成一堆卡片后再一点点骂回去。&lt;/p&gt;
&lt;p&gt;我会这样用：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;新项目先用 &lt;code&gt;design-taste-frontend&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;Codex / GPT 项目可以试 &lt;code&gt;gpt-taste&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;已有项目改版用 &lt;code&gt;redesign-existing-projects&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;有明确风格时再加 &lt;code&gt;minimalist-ui&lt;/code&gt;、&lt;code&gt;high-end-visual-design&lt;/code&gt; 或 &lt;code&gt;industrial-brutalist-ui&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;如果 AI 老是留 TODO 或省略代码，再加 &lt;code&gt;full-output-enforcement&lt;/code&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;它不是万能审美按钮&#34;&gt;它不是万能审美按钮
&lt;/h2&gt;&lt;p&gt;Taste Skill 解决的是“AI 前端输出太模板”的问题，但它不是设计师替代品。&lt;/p&gt;
&lt;p&gt;几个边界要说清楚：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;它不能替你定义品牌定位；&lt;/li&gt;
&lt;li&gt;它不能保证每次生成都好看；&lt;/li&gt;
&lt;li&gt;它更适合有前端审美基础的人做二次判断；&lt;/li&gt;
&lt;li&gt;Skill 写得再细，也需要你提供产品背景、受众和功能优先级；&lt;/li&gt;
&lt;li&gt;已有设计系统的团队，不应该让 skill 覆盖内部规范。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;换句话说，它更像一个“前端生成的审美脚手架”。它能把默认下限抬高，但最终效果还是要靠你审稿、截图、调 CSS 和真实设备检查。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;taste-skill&lt;/code&gt; 的价值在于，它把很多前端设计经验变成了 Agent 可执行的规则。对 Codex、Cursor、Claude Code 这类工具来说，这种 skill 很适合补齐“会写代码但容易没品”的短板。&lt;/p&gt;
&lt;p&gt;如果你经常用 AI 生成前端页面，尤其受够了大渐变、大圆角、满屏卡片、随机图标和没层级的模板感界面，可以把它当成一个起点。但别把它当成设计总监，真实项目仍然需要你自己做取舍。&lt;/p&gt;
&lt;h2 id=&#34;参考来源&#34;&gt;参考来源
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/Leonxlnx/taste-skill&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Leonxlnx/taste-skill - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>subagent 会多花多少 token？多 agent 成本与使用策略</title>
        <link>https://knightli.com/2026/05/31/subagent-multi-agent-token-cost/</link>
        <pubDate>Sun, 31 May 2026 14:17:42 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/31/subagent-multi-agent-token-cost/</guid>
        <description>&lt;p&gt;使用 subagent 或多 agent 工作流，通常都会增加 token 用量。区别不在于“会不会增加”，而在于增加多少、换来的并行效率和稳定性是否值得。&lt;/p&gt;
&lt;p&gt;如果任务很小，直接让主 agent 完成通常更省。只有当任务可以清楚拆分，或者需要独立复查时，subagent 才更容易体现价值。&lt;/p&gt;
&lt;h2 id=&#34;subagent-不是更便宜的并行线程&#34;&gt;subagent 不是更便宜的并行线程
&lt;/h2&gt;&lt;p&gt;很多人第一次看到 subagent，会下意识把它理解成“并行线程”：主 agent 做一部分，subagent 做另一部分，速度变快，所以应该更划算。&lt;/p&gt;
&lt;p&gt;实际不是这样。subagent 本质上也是一个独立的模型调用。它需要读任务说明、理解上下文、读取文件、分析问题，再输出结果。也就是说，它不是主 agent 的免费副本，而是额外启动了一条推理链路。&lt;/p&gt;
&lt;p&gt;所以使用 subagent 的核心判断不是“能不能并行”，而是“并行带来的时间节省、质量提升，是否值得额外 token 成本”。&lt;/p&gt;
&lt;h2 id=&#34;为什么会增加-token&#34;&gt;为什么会增加 token
&lt;/h2&gt;&lt;p&gt;一次 subagent 调用通常会额外消耗这些 token：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主 agent 写给 subagent 的任务说明；&lt;/li&gt;
&lt;li&gt;传递给 subagent 的上下文；&lt;/li&gt;
&lt;li&gt;subagent 自己读取文件和分析问题；&lt;/li&gt;
&lt;li&gt;subagent 生成结果或修改说明；&lt;/li&gt;
&lt;li&gt;主 agent 回收结果后的复查、整合和验证。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果多个 agent 读取同一批大文件，重复消耗会更明显。尤其是代码库分析、长文档翻译、批量内容整理这类任务，如果拆分不好，token 会花在重复理解上下文上。&lt;/p&gt;
&lt;h2 id=&#34;重复读取上下文是最大的-token-浪费&#34;&gt;重复读取上下文是最大的 token 浪费
&lt;/h2&gt;&lt;p&gt;subagent 真正浪费 token 的地方，往往不是“多开了一个 agent”，而是多个 agent 反复读同一批材料。&lt;/p&gt;
&lt;p&gt;比如一个任务要处理 6 篇文章，如果 4 个 agent 都先读完整站点结构、完整技能文档、完整文章列表，再各自处理一点点内容，那么并行会很贵。更好的做法是先由主 agent 确定边界，再让每个 subagent 只读自己负责的文章目录。&lt;/p&gt;
&lt;p&gt;更省 token 的拆法通常是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个 agent 只负责一个明确目录；&lt;/li&gt;
&lt;li&gt;给 subagent 的上下文越短越好；&lt;/li&gt;
&lt;li&gt;不让多个 agent 重复做同一类探索；&lt;/li&gt;
&lt;li&gt;主 agent 最后统一复查，而不是让每个 agent 都做全量复查；&lt;/li&gt;
&lt;li&gt;能用脚本统一检查的部分，不交给多个 agent 反复检查。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;换句话说，subagent 的成本控制重点是边界，而不是数量。&lt;/p&gt;
&lt;h2 id=&#34;大概会增加多少&#34;&gt;大概会增加多少
&lt;/h2&gt;&lt;p&gt;下面是一个粗略估算，实际消耗取决于上下文长度、文件大小、任务复杂度和 agent 数量。&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;场景&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;token 增加&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;单个 subagent 处理一个小任务&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;约 &lt;code&gt;1.2x - 2x&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2-4 个 agent 并行处理可拆分任务&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;约 &lt;code&gt;2x - 5x&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;多个 agent 各自读取大量文件、做长分析&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;可能 &lt;code&gt;5x+&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;主 agent 和 subagent 重复读同一批大文件&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;浪费最明显&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这不是精确计费公式，只是经验范围。真正的消耗还要看每个 agent 是否需要读完整文件、是否需要长推理、是否会反复等待和补充上下文。&lt;/p&gt;
&lt;h2 id=&#34;如何给-subagent-写更省-token-的任务说明&#34;&gt;如何给 subagent 写更省 token 的任务说明
&lt;/h2&gt;&lt;p&gt;任务说明越宽泛，subagent 越容易自己去探索上下文，token 消耗也越高。更省的写法是把边界写清楚。&lt;/p&gt;
&lt;p&gt;一个好的 subagent 任务说明应该包含：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;只允许处理哪些文件或目录；&lt;/li&gt;
&lt;li&gt;哪些文件只能读，哪些文件可以写；&lt;/li&gt;
&lt;li&gt;已有文件是否允许覆盖；&lt;/li&gt;
&lt;li&gt;需要保留哪些字段，比如 &lt;code&gt;date&lt;/code&gt;、&lt;code&gt;slug&lt;/code&gt;、&lt;code&gt;aliases&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;输出时只汇报什么结果；&lt;/li&gt;
&lt;li&gt;不需要做哪些事情，比如不要跑完整构建、不要改无关文件。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如，处理翻译时，不要只写“把文章翻译成多语言”。更省 token 的写法是：“只处理 &lt;code&gt;content/post/2026/05/240&lt;/code&gt;，读取 &lt;code&gt;index.zh-cn.md&lt;/code&gt;，只创建缺失的 &lt;code&gt;index.en.md&lt;/code&gt;、&lt;code&gt;index.zh-tw.md&lt;/code&gt;、&lt;code&gt;index.ja.md&lt;/code&gt;、&lt;code&gt;index.es.md&lt;/code&gt;，已存在则跳过，保留 &lt;code&gt;date&lt;/code&gt; 和 &lt;code&gt;slug&lt;/code&gt;。”&lt;/p&gt;
&lt;p&gt;这种说明更长一点，但能减少 subagent 自行猜测和重复探索，整体通常更省。&lt;/p&gt;
&lt;h2 id=&#34;按文件目录拆分比按语言步骤拆分更省&#34;&gt;按文件/目录拆分，比按语言/步骤拆分更省
&lt;/h2&gt;&lt;p&gt;如果是批量文章翻译，按“文章目录”拆通常比按“语言”拆更好。&lt;/p&gt;
&lt;p&gt;比如要翻译 6 篇文章，每篇都要生成英文、繁体、日文、西语。更推荐让一个 agent 负责一篇文章目录内的所有语言，而不是让一个 agent 负责所有英文、另一个负责所有日文。&lt;/p&gt;
&lt;p&gt;原因很简单：一篇文章的 front matter、代码块、链接、表格和语义上下文只需要读一次。如果按语言拆，多个 agent 会重复读取同一篇源文，token 会被放大。&lt;/p&gt;
&lt;p&gt;同样的逻辑也适用于代码任务。优先按模块、目录、组件拆分，而不是按“先分析、再实现、再测试”这种步骤拆分。步骤拆分很容易让每个 agent 都重新读一遍上下文。&lt;/p&gt;
&lt;h2 id=&#34;什么情况下值得用&#34;&gt;什么情况下值得用
&lt;/h2&gt;&lt;p&gt;subagent 的价值主要在两点：并行和独立视角。&lt;/p&gt;
&lt;p&gt;适合使用的场景包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;多篇文章批量翻译；&lt;/li&gt;
&lt;li&gt;多个目录可以独立修改；&lt;/li&gt;
&lt;li&gt;前端、后端、测试可以明确分工；&lt;/li&gt;
&lt;li&gt;一个 agent 写实现，另一个 agent 做风险复查；&lt;/li&gt;
&lt;li&gt;高风险修改需要第二视角检查。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这类任务里，token 会增加，但总耗时可能明显下降，而且每个 agent 只盯一块内容，注意力更集中。&lt;/p&gt;
&lt;h2 id=&#34;什么时候值得用一个-agent-做复查&#34;&gt;什么时候值得用一个 agent 做复查
&lt;/h2&gt;&lt;p&gt;复查型 agent 不一定总值得用。它适合风险高、影响面大、主 agent 容易遗漏细节的任务。&lt;/p&gt;
&lt;p&gt;比较值得加复查 agent 的情况包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;修改涉及登录、支付、权限、数据删除；&lt;/li&gt;
&lt;li&gt;多语言内容会影响分类、URL、站内链接；&lt;/li&gt;
&lt;li&gt;大范围重构后需要独立找回归风险；&lt;/li&gt;
&lt;li&gt;用户明确要求 code review 或风险审查；&lt;/li&gt;
&lt;li&gt;主 agent 已经做了实现，但需要第二视角看边界条件。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不值得加复查 agent 的情况也很明确：单文件小改、标题微调、简单 front matter 修正、只跑一个命令。这些任务主 agent 自查就够了。&lt;/p&gt;
&lt;h2 id=&#34;什么情况下不值得用&#34;&gt;什么情况下不值得用
&lt;/h2&gt;&lt;p&gt;不适合使用 subagent 的场景很常见：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;单文件小改；&lt;/li&gt;
&lt;li&gt;简单问答；&lt;/li&gt;
&lt;li&gt;只需要跑一个命令；&lt;/li&gt;
&lt;li&gt;改动范围很小；&lt;/li&gt;
&lt;li&gt;任务不能清楚拆分；&lt;/li&gt;
&lt;li&gt;subagent 必须反复等待主 agent 提供上下文。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这类任务用 subagent 往往只是增加开销。主 agent 直接处理更快，也更省 token。&lt;/p&gt;
&lt;h2 id=&#34;我的默认策略省-token-优先风险任务才加复查&#34;&gt;我的默认策略：省 token 优先，风险任务才加复查
&lt;/h2&gt;&lt;p&gt;如果目标是尽量节省 token，可以采用下面这套策略：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;小任务：不用 subagent。&lt;/li&gt;
&lt;li&gt;中等任务：不用 subagent。&lt;/li&gt;
&lt;li&gt;大批量任务：默认也不用 subagent，除非用户明确要并行提速。&lt;/li&gt;
&lt;li&gt;高风险任务：可以多用一个 agent 做复查，用 token 换稳定性。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这套策略更偏保守。它牺牲了一部分并行速度，但能减少重复读取上下文和重复推理带来的 token 消耗。&lt;/p&gt;
&lt;p&gt;如果任务很大但不高风险，我也会优先考虑脚本、批量检查和本地结构化处理。只有当拆分非常清楚，或者用户明确希望并行提速时，才更适合引入多个 agent。&lt;/p&gt;
&lt;h2 id=&#34;更均衡的策略&#34;&gt;更均衡的策略
&lt;/h2&gt;&lt;p&gt;如果既想控制成本，又不想完全放弃并行，可以采用折中方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;默认主 agent 直接做；&lt;/li&gt;
&lt;li&gt;只有任务能按文件或目录明确拆分时才考虑 subagent；&lt;/li&gt;
&lt;li&gt;subagent 只读取自己负责的文件；&lt;/li&gt;
&lt;li&gt;不让多个 agent 同时读同一批大文件；&lt;/li&gt;
&lt;li&gt;主 agent 最后统一复查关键字段、测试结果和 Git diff；&lt;/li&gt;
&lt;li&gt;高风险任务才增加一个独立复查 agent。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这能避免“为了并行而并行”。subagent 应该服务于明确的效率或质量目标，而不是成为默认动作。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;subagent 和多 agent 一定会增加 token 用量。单个 subagent 可能只是增加一点，多个 agent 并行时则可能成倍增加。&lt;/p&gt;
&lt;p&gt;是否值得用，取决于任务本身：如果任务能清楚拆分，或者风险高到需要独立复查，额外 token 可能是值得的；如果只是单文件小改、简单问答或常规检查，直接由主 agent 完成更省。&lt;/p&gt;
&lt;p&gt;一句话总结：&lt;strong&gt;小任务省 token，大任务看拆分，高风险才用额外 agent 换稳定性。&lt;/strong&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>GPT-5.6 爆料：150 万 token 上下文窗口意味着什么</title>
        <link>https://knightli.com/2026/05/27/gpt-5-6-rumor-1-5m-context-window/</link>
        <pubDate>Wed, 27 May 2026 13:55:06 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/27/gpt-5-6-rumor-1-5m-context-window/</guid>
        <description>&lt;p&gt;2026 年 5 月 26 日，有爆料称多名开发者在 OpenAI Codex 后端日志中发现了尚未官宣的 GPT-5.6 相关痕迹，其中一个内部代号为 &lt;code&gt;iris-alpha&lt;/code&gt;，传闻支持 150 万 token 上下文窗口，并可能在 2026 年 6 月发布。&lt;/p&gt;
&lt;p&gt;这类信息目前仍属于爆料，不等于 OpenAI 官方发布。更稳妥的看法是：它展示了下一代大模型可能继续沿着“更长上下文、更强代码能力、更好前端生成”几个方向推进。&lt;/p&gt;
&lt;h2 id=&#34;爆料里提到哪些模型代号&#34;&gt;爆料里提到哪些模型代号
&lt;/h2&gt;&lt;p&gt;报道提到，开发者在相关日志中看到的不只 &lt;code&gt;iris-alpha&lt;/code&gt;，还包括 &lt;code&gt;ember-alpha&lt;/code&gt; 和 &lt;code&gt;beacon-alpha&lt;/code&gt; 等版本。&lt;/p&gt;
&lt;p&gt;这些名字现阶段更像内部测试代号。它们是否都属于 GPT-5.6 系列、最终会不会对应公开 API 模型、发布时间是否会改变，都还没有官方确认。&lt;/p&gt;
&lt;p&gt;所以不要急着把这些代号当成最终产品名。真正值得关注的是它们暴露出来的能力方向。&lt;/p&gt;
&lt;h2 id=&#34;150-万-token-上下文为什么重要&#34;&gt;150 万 token 上下文为什么重要
&lt;/h2&gt;&lt;p&gt;报道里最醒目的数字是 150 万 token 上下文窗口。&lt;/p&gt;
&lt;p&gt;爆料中给出的对比是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当前 GPT-5.5 API 为 105 万 token&lt;/li&gt;
&lt;li&gt;Codex OAuth 渠道约为 40 万 token&lt;/li&gt;
&lt;li&gt;GPT-5.6 传闻提升到 150 万 token&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上下文窗口决定模型单次能接收和利用多少信息。它包括用户输入、历史对话、系统提示、文件内容、日志、代码 diff、测试输出等。&lt;/p&gt;
&lt;p&gt;如果这个数字属实，GPT-5.6 对几类任务会更有意义：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;阅读大型代码仓库&lt;/li&gt;
&lt;li&gt;分析长篇合同或技术文档&lt;/li&gt;
&lt;li&gt;连续跟踪复杂项目&lt;/li&gt;
&lt;li&gt;保留更长的 agent 工作历史&lt;/li&gt;
&lt;li&gt;在一次任务里处理更多文件和更多测试反馈&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但上下文窗口变大，不代表模型一定“更聪明”。它只是让模型能看到更多材料。模型是否能从长上下文里准确检索、归纳、保持目标一致，还要看训练、推理策略和工具调用能力。&lt;/p&gt;
&lt;h2 id=&#34;真实世界测试的信号&#34;&gt;真实世界测试的信号
&lt;/h2&gt;&lt;p&gt;报道还提到，有开发者在辅助工具 OpenCode 中做了较极端的真实世界测试：当输入达到约 90 万 token 时，模型仍能流畅响应，甚至处理超过 105 万 token 的请求。&lt;/p&gt;
&lt;p&gt;如果这个反馈准确，它说明 OpenAI 可能不仅在扩展理论窗口，也在处理长输入下的响应稳定性。&lt;/p&gt;
&lt;p&gt;对 AI 编程来说，这点比“窗口数字”本身更重要。开发任务里的上下文往往不是干净的长文本，而是代码、日志、错误栈、依赖文件、配置文件和用户指令混在一起。模型不仅要装得下，还要找得准。&lt;/p&gt;
&lt;h2 id=&#34;前端界面生成能力也被提到&#34;&gt;前端界面生成能力也被提到
&lt;/h2&gt;&lt;p&gt;这次爆料还提到了 GPT-5.6 的前端生成能力。&lt;/p&gt;
&lt;p&gt;据报道，爆料截图中模型在几乎没有详细提示词的情况下，生成了一个名为 &lt;code&gt;Lumen Notes&lt;/code&gt; 的极简记事应用界面。报道强调的表现包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;栅格布局更成熟&lt;/li&gt;
&lt;li&gt;配色更克制&lt;/li&gt;
&lt;li&gt;字体层级更清晰&lt;/li&gt;
&lt;li&gt;导航结构更完整&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果这类能力稳定，AI 编程模型的价值会继续从“能写代码”转向“能生成更接近可用产品的界面”。这也是 Codex、Claude Code、Cursor、Gemini CLI 等工具最近都在推进的方向：不只是补函数，而是从需求到界面、测试、修复形成闭环。&lt;/p&gt;
&lt;h2 id=&#34;还提到了哪些竞争模型&#34;&gt;还提到了哪些竞争模型
&lt;/h2&gt;&lt;p&gt;同一批爆料还提到，Anthropic 的 Claude Sonnet 4.8、Google 的 Gemini 3.5 Pro，以及 xAI 的 Grok 5，都可能瞄准 2026 年 6 月发布。&lt;/p&gt;
&lt;p&gt;这部分同样要按传闻看待。即便多个模型确实都在 6 月前后更新，最终能力也要等官方文档、API 实测和真实开发任务验证。&lt;/p&gt;
&lt;p&gt;不过大方向很清楚：模型厂商的竞争已经不只是聊天能力，而是更长上下文、更强工具调用、更稳的代码编辑、更好的 UI 生成，以及更适合 agent 长任务的可靠性。&lt;/p&gt;
&lt;h2 id=&#34;我的判断&#34;&gt;我的判断
&lt;/h2&gt;&lt;p&gt;如果 GPT-5.6 的 150 万 token 上下文窗口最终成真，它对 Codex 这类编程 agent 的意义会比普通聊天更大。&lt;/p&gt;
&lt;p&gt;因为 agent 编程天然会消耗大量上下文：读仓库、跑测试、看日志、比较 diff、保留用户偏好、连续修复问题。上下文越长，agent 越有机会在一次任务里保留完整线索。&lt;/p&gt;
&lt;p&gt;但我更关心三个实际问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;长上下文下的定位能力是否稳定。&lt;/li&gt;
&lt;li&gt;大量日志和代码混合输入时，模型是否会被噪音带偏。&lt;/li&gt;
&lt;li&gt;API、Codex、ChatGPT、OAuth 等不同入口是否会给出一致的上下文上限。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所以这条爆料可以关注，但不适合过早下结论。等 OpenAI 官方发布模型卡、API 文档和真实价格之后，再判断 GPT-5.6 是否真的适合大型代码仓库和长任务 agent 工作流，会更稳。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Codex 官方文章解读：如何把 Codex 用到极致</title>
        <link>https://knightli.com/2026/05/27/getting-the-most-out-of-codex/</link>
        <pubDate>Wed, 27 May 2026 08:21:18 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/27/getting-the-most-out-of-codex/</guid>
        <description>&lt;p&gt;多数开发者第一次使用 Codex，通常是从代码任务开始：阅读仓库、修改 diff、运行测试、打开 pull request。&lt;/p&gt;
&lt;p&gt;这仍然是 Codex 的核心场景。但电脑上的很多工作本来就被代码和工具包围：执行 shell 命令、浏览网页、调用 API、导出文档、响应消息、触发自动化。随着这些能力逐渐接入 Codex，它就不再只是狭义的代码助手，而更像一个帮你完成电脑工作的系统。&lt;/p&gt;
&lt;p&gt;Codex app 让这种变化变得更具体。一个 thread 可以保留上下文、调用工具、展示产物，并在多轮提示之间持续推进，而不是每次对话都重新开始。&lt;/p&gt;
&lt;p&gt;想更充分地使用 Codex，关键是把这些能力组合起来：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;持久线程，用来保存长期上下文&lt;/li&gt;
&lt;li&gt;语音输入、steering 和 queuing，让用户仍然掌控过程&lt;/li&gt;
&lt;li&gt;browser、computer use、MCP servers 和 connectors，让 Codex 走出仓库&lt;/li&gt;
&lt;li&gt;thread automations 和 Goals，让任务在用户离开后继续推进&lt;/li&gt;
&lt;li&gt;侧边栏，用来审阅代码、文档、幻灯片、网页和其他产物&lt;/li&gt;
&lt;li&gt;共享记忆，把重要上下文写到线程之外&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;持久线程&#34;&gt;持久线程
&lt;/h2&gt;&lt;p&gt;Durable threads 指的是能在多次会话之间保留工作上下文的长线程。&lt;/p&gt;
&lt;p&gt;Pinned threads 是一种很实用的入口。它适合放那些会反复回来的工作流，比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Chief of Staff 线程&lt;/li&gt;
&lt;li&gt;发布线程&lt;/li&gt;
&lt;li&gt;文档审阅线程&lt;/li&gt;
&lt;li&gt;外部监控线程&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些不是临时聊天，而是持续存在的工作空间。Codex 可以在后续继续回到同一个线程，沿用之前的决策、偏好和背景信息，避免每次都从零重建上下文。&lt;/p&gt;
&lt;p&gt;快捷键也让它更顺手。&lt;code&gt;Command-1&lt;/code&gt; 到 &lt;code&gt;Command-9&lt;/code&gt; 可以直接跳转到已保存的线程。&lt;/p&gt;
&lt;h2 id=&#34;语音输入&#34;&gt;语音输入
&lt;/h2&gt;&lt;p&gt;语音输入的价值在于，它能捕捉还没有被整理成正式文字的想法。&lt;/p&gt;
&lt;p&gt;Codex 内置语音输入。它特别适合那些说起来很自然、打字时却很别扭的模糊起点：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;我记得 Slack 里好像有个叫 Ben 的人提过这个。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;具体细节我不记得了。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;帮我去找一下。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;对于一个能搜索、整理上下文并汇报结果的 agent 来说，这通常已经足够开始。&lt;/p&gt;
&lt;p&gt;语音也适合两三分钟的想法倾倒。会议转录、口述规划笔记、未整理的原始记录，往往比一句摘要更有用，因为它们保留了不确定性、重点和没说完的思路。&lt;/p&gt;
&lt;h2 id=&#34;steering-和-queuing&#34;&gt;Steering 和 queuing
&lt;/h2&gt;&lt;p&gt;语音和显式控制结合起来时，会更有用。&lt;/p&gt;
&lt;p&gt;Steering 指的是在 Codex 任务执行过程中插入新的方向，让它在当前步骤结束前改道。&lt;/p&gt;
&lt;p&gt;例如在审阅网页时，用户可以一边在侧边栏标注，一边打断当前任务：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;这里再小一点。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;这两个元素之间的间距不对。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;这句文案写错了。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Queuing 则不同。它不打断当前任务，而是把下一步工作排到队列里：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;这项工作完成后，把预览链接发给 Slack 里的 reviewer。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Steering 改变 Codex 现在正在做什么。Queuing 改变它接下来应该做什么。两者都让用户在任务展开时仍然靠近现场。&lt;/p&gt;
&lt;h2 id=&#34;工具和可触达范围&#34;&gt;工具和可触达范围
&lt;/h2&gt;&lt;p&gt;线程有了连续性之后，下一个问题就是：它能操作什么？&lt;/p&gt;
&lt;p&gt;Codex 可以一层层向外扩展：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$browser&lt;/code&gt;：适合侧边栏里的网页检查、标注和 review&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@chrome&lt;/code&gt;：适合依赖用户 Chrome 登录状态的浏览器工作流&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@computer&lt;/code&gt;：适合只能通过桌面 GUI 完成的任务&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MCP servers 和 connectors 把同样的思路扩展到更多工作流中。Slack、Gmail、Calendar 很重要，因为很多任务最初不是以代码形式出现，而是以消息、邮件和日程问题出现。&lt;/p&gt;
&lt;p&gt;Skills 则适合固化重复工作。当某个流程已经被证明有用，就可以把它打包成 skill，让 Codex 下次不必重新学习这套步骤。&lt;/p&gt;
&lt;h2 id=&#34;从任何地方继续工作&#34;&gt;从任何地方继续工作
&lt;/h2&gt;&lt;p&gt;Codex mobile app 改变了用户必须坐在电脑前的时间。&lt;/p&gt;
&lt;p&gt;一个任务可以在 Mac 上开始，因为文件、权限和本地环境都在那里；随后用户离开桌面，只用手机继续确认、补充或改方向。&lt;/p&gt;
&lt;p&gt;这在很多小场景里很有价值：Codex 跑长任务时，用户可以离开座位；如果它需要确认，可以在外面回复；如果方向错了，也能及时 redirect。真正留在原地的是本地环境，而不是用户本人。&lt;/p&gt;
&lt;h2 id=&#34;自动化&#34;&gt;自动化
&lt;/h2&gt;&lt;p&gt;Automations 可以按计划运行 Codex 工作。&lt;/p&gt;
&lt;p&gt;如果一个周期任务应该从某个 workspace 重新开始，例如日报或常规仓库检查，可以用 scheduled automation。如果调度应该回到一个已有对话，并沿用它的上下文，就更适合 thread automation。&lt;/p&gt;
&lt;p&gt;Thread automations 更像心跳式唤醒：按固定节奏回到同一个 Codex thread。&lt;/p&gt;
&lt;p&gt;Pinned threads 需要用户主动回来，而 thread automation 可以每几分钟或每几小时检查一次，持续运行到满足条件为止，并随时间调整节奏。&lt;/p&gt;
&lt;p&gt;例如，一个 Chief of Staff 线程可以每 30 分钟运行一次：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;每 30 分钟检查 Slack 和 Gmail，找出需要我注意但还没有回复的消息。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;帮我判断哪些最重要。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;如果有人问我问题，尽可能深入研究答案，并替我起草回复，但不要发送。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;用户回来时，最耗时的上下文收集往往已经完成。真正要不要发送，仍然由人决定。&lt;/p&gt;
&lt;p&gt;Thread automations 也适合反馈循环。它可以定期查看 pull request 评论、Google Docs 评论或 Slack 回复，在用户离开时继续推进周边工作。&lt;/p&gt;
&lt;p&gt;比如一个动画工作流：reviewer 在 Slack 里发来视频反馈，thread automation 定时检查线程；如果有新评论，就重新渲染版本，并在同一个 Slack thread 里回复 reviewer。如果某个集成无法完成最终上传，桌面自动化还可以通过 GUI 补上最后一步。&lt;/p&gt;
&lt;p&gt;这个循环会跨过 Slack、代码库和桌面应用，但对用户来说仍然留在同一个工作流里。&lt;/p&gt;
&lt;h2 id=&#34;goals&#34;&gt;Goals
&lt;/h2&gt;&lt;p&gt;Goals 最适合那些有明确终点、并且 agent 可以持续推进的任务。&lt;/p&gt;
&lt;p&gt;一个较弱的 goal 可能是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;实现这个 Markdown 文件里的计划。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;更强的 goal 会有可衡量的完成标准。&lt;/p&gt;
&lt;p&gt;例如，把一个内部工具从 Python 迁移到 Rust 时，可以先建好新目录，再把目标说清楚：新实现只有在单元测试通过后才算完成。&lt;/p&gt;
&lt;p&gt;Goal 本质上是持续执行加验证器。用户需要定义结果、停止条件，以及判断 Codex 是否更接近目标的信号。&lt;/p&gt;
&lt;p&gt;常见的验证器包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;测试套件&lt;/li&gt;
&lt;li&gt;benchmark&lt;/li&gt;
&lt;li&gt;bug reproduction&lt;/li&gt;
&lt;li&gt;validation matrix&lt;/li&gt;
&lt;li&gt;必须持续通过的端到端工作流&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;任务可以有野心，但没有验证条件时，它更像愿望，而不是 goal。&lt;/p&gt;
&lt;h2 id=&#34;侧边栏&#34;&gt;侧边栏
&lt;/h2&gt;&lt;p&gt;侧边栏把工作产物放在生成它的对话旁边。用户不必导出文件、切换上下文，再回头描述问题。产物可能是代码，也可能是 deck、PDF、网页、表格，或者工作过程中生成的其他 artifact。&lt;/p&gt;
&lt;p&gt;它特别适合四类工作：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;检查 artifact&lt;/li&gt;
&lt;li&gt;标注需要修改的地方&lt;/li&gt;
&lt;li&gt;操作网页界面&lt;/li&gt;
&lt;li&gt;审阅变更&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Markdown、表格、数据表、文档和幻灯片都可以直接在侧边栏里看。用户可以检查、标注、修改，而不用把这个过程变成另一轮交接。&lt;/p&gt;
&lt;p&gt;如果是 deck 或 PDF，它可以一直停在产生它的 thread 旁边，随时接受 review 和修复。&lt;/p&gt;
&lt;p&gt;浏览器也是类似的工作面。Codex 可以打开渲染后的页面，检查它，响应用户在页面上的标注，并继续修复同一个对象。网页既是输出结果，也是控制表面。&lt;/p&gt;
&lt;p&gt;这些表面尤其适合放在侧边栏里：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;index.html&lt;/code&gt; 这种轻量静态 artifact&lt;/li&gt;
&lt;li&gt;Storybook&lt;/li&gt;
&lt;li&gt;Remotion Studio&lt;/li&gt;
&lt;li&gt;浏览器幻灯片&lt;/li&gt;
&lt;li&gt;数据分析应用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一个单独的 &lt;code&gt;index.html&lt;/code&gt; 文件就可以成为长期存在的交互 artifact，不一定需要服务器。Thread automations 也可以定期刷新静态 artifact，让用户回来时看到新的结果。&lt;/p&gt;
&lt;h2 id=&#34;共享记忆&#34;&gt;共享记忆
&lt;/h2&gt;&lt;p&gt;长线程很有用，但重要上下文不应该只存在于对话记录里。&lt;/p&gt;
&lt;p&gt;Shared memory 指的是把持久上下文存放在线程之外，让未来的工作可以从明确、可审阅的地方继续。&lt;/p&gt;
&lt;p&gt;一种稳定做法是把持久线程锚定在 Obsidian vault 里。实际形态可以很简单：一组普通文件，方便检查、编辑、移动和长期保存。团队可以把它放在 cloud storage、Git、Dropbox、Google Drive 或其他同步层里。&lt;/p&gt;
&lt;p&gt;一个 vault 可能长这样：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;vault/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── TODO.md
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── people/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── projects/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── agent/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└── notes/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;顶层的 &lt;code&gt;AGENTS.md&lt;/code&gt; 可以说明 Codex 应该如何维护这个工作空间：什么信息要写下来，写到哪里，什么时候不要制造噪音。&lt;/p&gt;
&lt;p&gt;一个实用的 &lt;code&gt;AGENTS.md&lt;/code&gt; 可以这样写：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Treat ~/vault as durable work memory.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Prefer canonical notes over note sprawl.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Route TODOs, people, projects, daily summaries, and scratch notes explicitly.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Preserve decisions, blockers, owners, dates, and useful links.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; If nothing meaningful changed, do not churn the vault.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;不要照抄某个 vault 结构。更重要的是教会 agent：长期上下文应该放在哪里，哪些信息值得保留，什么时候不应该反复改动文件。&lt;/p&gt;
&lt;p&gt;仓库存放代码。Vault 存放滚动上下文：相关人员、发生了什么、哪里卡住、谁负责、下一步是什么，以及那些如果不写下来就会在会话之间消失的细节。&lt;/p&gt;
&lt;p&gt;Codex 也有第一方记忆能力，可以在 &lt;code&gt;Settings &amp;gt; Personalization &amp;gt; Memories&lt;/code&gt; 中配置。它适合记录偏好、重复工作流和常见坑点，但它更适合作为显式 written context 的补充，而不是替代品。Chronicle 也在同一个方向上推进：从最近的屏幕上下文中帮助 Codex 建立记忆。&lt;/p&gt;
&lt;h2 id=&#34;从代码向外扩展&#34;&gt;从代码向外扩展
&lt;/h2&gt;&lt;p&gt;Codex 仍然从代码开始。但代码周围的更多工作，现在也能被同一个系统触达：MCP servers、浏览器界面、桌面控制、thread automations 和可审阅 artifact。&lt;/p&gt;
&lt;p&gt;这改变了使用 Codex 的控制方式。Steering 用来打断正在进行的工作。Queuing 用来排下一步。Thread automations 让线程在用户离开后继续活动。Goals 给长期任务加上明确终点和验证信号。&lt;/p&gt;
&lt;p&gt;当这些能力连起来时，Codex 就能把一个工作流从指令推进到执行，再推进到 artifact review。即使任务已经离开代码仓库，它仍然可以留在同一个系统里完成。&lt;/p&gt;
&lt;p&gt;原文链接：&lt;a class=&#34;link&#34; href=&#34;https://x.com/jxnlco/status/2057153744630890620&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Getting the most out of Codex&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Codex Goal 设置目标失败：Failed to set goal 怎么处理</title>
        <link>https://knightli.com/2026/05/27/codex-goal-failed-to-set-goal-config-toml/</link>
        <pubDate>Wed, 27 May 2026 08:17:57 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/27/codex-goal-failed-to-set-goal-config-toml/</guid>
        <description>&lt;p&gt;最近有用户反馈，使用 Codex Goal 时会立即出现 &lt;code&gt;Failed to set goal&lt;/code&gt; 或“设置目标失败”的错误。这个错误和 prompt 长短无关，在 Codex 应用和 VS Code 扩展里都可能出现。&lt;/p&gt;
&lt;p&gt;从讨论里的反馈看，这个问题更像是本地功能开关或配置状态异常，而不是目标内容本身写错了。&lt;/p&gt;
&lt;h2 id=&#34;先检查-goals-功能开关&#34;&gt;先检查 goals 功能开关
&lt;/h2&gt;&lt;p&gt;最直接的处理方法，是检查 Codex 的配置文件：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;~/&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;codex&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;toml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;确认里面有 &lt;code&gt;[features]&lt;/code&gt; 段，并开启 &lt;code&gt;goals&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;features&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;goals&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果已经有 &lt;code&gt;[features]&lt;/code&gt;，只需要在该段下面补上 &lt;code&gt;goals = true&lt;/code&gt;。如果没有这个段，就新建一个。&lt;/p&gt;
&lt;p&gt;改完以后，重启 Codex 应用或 VS Code 扩展，再重新尝试设置 Goal。&lt;/p&gt;
&lt;h2 id=&#34;如果还有问题检查配置目录&#34;&gt;如果还有问题，检查配置目录
&lt;/h2&gt;&lt;p&gt;讨论里也有人提到，&lt;code&gt;.codex&lt;/code&gt; 目录里的缓存或临时文件异常时，也可能触发类似问题。&lt;/p&gt;
&lt;p&gt;比较稳妥的处理顺序是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先备份 &lt;code&gt;~/.codex/config.toml&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;关闭 Codex 相关应用。&lt;/li&gt;
&lt;li&gt;临时移走或重命名 &lt;code&gt;~/.codex&lt;/code&gt; 目录。&lt;/li&gt;
&lt;li&gt;重新打开 Codex，让它重建配置目录。&lt;/li&gt;
&lt;li&gt;再把原来的 &lt;code&gt;config.toml&lt;/code&gt; 里需要的配置合并回来。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;不要直接删除配置目录，尤其是里面可能有你手动维护的配置、技能、会话或其它本地状态。&lt;/p&gt;
&lt;h2 id=&#34;windows-上还要留意安全软件&#34;&gt;Windows 上还要留意安全软件
&lt;/h2&gt;&lt;p&gt;也有反馈提到，Windows Defender 可能会把 &lt;code&gt;config.toml&lt;/code&gt; 当成可疑文件。这不一定是所有人的原因，但如果你在 Windows 上遇到同样问题，可以顺手检查一下安全软件的隔离记录。&lt;/p&gt;
&lt;p&gt;如果配置文件被隔离、改名或阻止访问，Codex 读取不到功能开关，也可能表现为 Goal 无法启用。&lt;/p&gt;
&lt;h2 id=&#34;判断是不是-prompt-的问题&#34;&gt;判断是不是 prompt 的问题
&lt;/h2&gt;&lt;p&gt;一个简单判断方法是：用极短目标测试。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;修复一个测试失败
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果极短目标也立即报 &lt;code&gt;Failed to set goal&lt;/code&gt;，基本就不是 prompt 写法问题，而是本地配置、功能开关、扩展状态或缓存目录问题。&lt;/p&gt;
&lt;p&gt;如果只有很长、很复杂的目标会失败，再考虑是否是目标内容太复杂、包含特殊链接、字段格式不被 UI 接受。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;Codex Goal 的 &lt;code&gt;Failed to set goal&lt;/code&gt; 可以按这个顺序排查：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;检查 &lt;code&gt;~/.codex/config.toml&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;在 &lt;code&gt;[features]&lt;/code&gt; 下加入 &lt;code&gt;goals = true&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;重启 Codex 应用或 VS Code 扩展。&lt;/li&gt;
&lt;li&gt;仍失败时，备份配置后重建 &lt;code&gt;~/.codex&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;Windows 用户额外检查 Defender 或安全软件是否误拦截配置文件。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这个问题的重点不是“目标怎么写”，而是先确认 Goal 功能本身是否在本地配置里正常启用。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Codex Goal 深度解析：让 AI Agent 连续工作数小时的目标驱动工作流</title>
        <link>https://knightli.com/2026/05/26/codex-goal-persistent-goals-ai-agent-long-running-workflow/</link>
        <pubDate>Tue, 26 May 2026 23:44:37 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/26/codex-goal-persistent-goals-ai-agent-long-running-workflow/</guid>
        <description>&lt;p&gt;浏览器、终端和 IDE 里的 AI Agent 已经越来越会写代码了，但很多人真正遇到的问题不是“它不会做”，而是“它做了一半就说完成了”。&lt;/p&gt;
&lt;p&gt;简单 ticket 很适合交给编程 Agent：修一个按钮、补一个接口、改一段文案、加一个测试。目标清楚，边界很小，验证方式也直接。但一旦任务变成大型迁移、跨模块重构、测试套件修复、依赖升级、prompt 评测优化，Agent 就很容易出现一种典型问题：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;它完成了一个看起来合理的中间状态，然后过早停下。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Codex Goal / Persistent Goals 这类能力要解决的，正是这个“提前收工”问题。它的重点不是让 Agent 多跑几轮，而是让 Agent 围绕明确目标持续推进，直到满足可验证的完成标准。&lt;/p&gt;
&lt;h2 id=&#34;codex-goal-解决的不是循环而是停止条件&#34;&gt;Codex Goal 解决的不是循环，而是停止条件
&lt;/h2&gt;&lt;p&gt;很多长任务自动化会从一个粗糙方案开始：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;继续检查代码，修复问题，直到没有错误。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;或者更机械一点：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;循环 10 次：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1. 运行测试
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2. 让模型修复失败
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;3. 再运行测试
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这类粗糙循环看起来能让 Agent 工作更久，但它有两个硬伤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;它不知道什么时候真的该停。&lt;/li&gt;
&lt;li&gt;它也不知道“没有继续报错”是否等于“任务完成”。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Codex Goal 的关键不是循环次数，而是 goal、state、judge stop condition 三件事。也就是说，Agent 需要知道这次工作的目标是什么，当前已经完成到哪里，以及哪些证据能证明任务真的结束了。&lt;/p&gt;
&lt;p&gt;这也是长任务 Agent 的核心分水岭：不是“多执行几步”，而是“能不能判断自己还差什么”。&lt;/p&gt;
&lt;h2 id=&#34;goal-和普通-prompt-的区别&#34;&gt;Goal 和普通 prompt 的区别
&lt;/h2&gt;&lt;p&gt;普通 prompt 更像一次性指令：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;把这个项目的测试修好。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Goal prompt 则更像一份小型任务合约：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;目标：修复当前仓库中失败的测试。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;范围：只修改 src/ 和 tests/，不要改构建脚本。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;完成标准：npm test 全部通过，且新增修改不引入 lint 错误。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;验证命令：npm test &amp;amp;&amp;amp; npm run lint。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;失败处理：如果超过 3 次仍无法修复，输出剩余失败用例、已尝试方案和阻塞点。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;输出：总结修改文件、修复原因、验证结果。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;两者最大的差别在于，Goal prompt 把“完成”定义清楚了。&lt;/p&gt;
&lt;p&gt;如果没有清晰的完成定义，Agent 很容易把“我改了代码”误判成“我完成了任务”。如果有明确的完成标准，Agent 就必须围绕测试、日志、diff、构建结果、eval 分数这些外部证据继续推进。&lt;/p&gt;
&lt;h2 id=&#34;为什么-llm-judge-stop-condition-很关键&#34;&gt;为什么 LLM judge stop condition 很关键
&lt;/h2&gt;&lt;p&gt;长任务里最难的不是让 Agent 执行命令，而是让它判断：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;现在是否真的完成了？&lt;/li&gt;
&lt;li&gt;是否只是通过了局部测试？&lt;/li&gt;
&lt;li&gt;是否修了一个问题，却引入了另一个问题？&lt;/li&gt;
&lt;li&gt;是否需要继续搜索、继续运行验证、继续回滚某个方向？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这就是 LLM judge stop condition 的价值。&lt;/p&gt;
&lt;p&gt;理想状态下，Agent 不应该只看“最后一个命令是否退出码为 0”。它还应该综合判断：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用户给出的完成标准是否全部满足；&lt;/li&gt;
&lt;li&gt;修改是否限定在允许范围内；&lt;/li&gt;
&lt;li&gt;测试、lint、build、eval 是否都跑过；&lt;/li&gt;
&lt;li&gt;失败日志是否还有未处理项；&lt;/li&gt;
&lt;li&gt;是否存在明显的副作用和风险；&lt;/li&gt;
&lt;li&gt;最终输出是否能让人类快速复核。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;换句话说，judge 不只是“判定成功”，还要防止 Agent 自我安慰式收尾。&lt;/p&gt;
&lt;h2 id=&#34;哪些任务适合交给-goal&#34;&gt;哪些任务适合交给 Goal
&lt;/h2&gt;&lt;p&gt;Codex Goal / Persistent Goals 更适合那些需要多轮探索和验证的复杂编程任务，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;代码迁移：从旧框架迁到新框架，从 CommonJS 迁到 ESM，从旧 API 迁到新 API。&lt;/li&gt;
&lt;li&gt;大型重构：拆分模块、整理边界、替换重复实现、降低复杂度。&lt;/li&gt;
&lt;li&gt;测试修复：连续分析失败用例，定位原因，修复后反复验证。&lt;/li&gt;
&lt;li&gt;依赖升级：升级框架、SDK、构建工具，同时处理破坏性变更。&lt;/li&gt;
&lt;li&gt;Prompt 评测优化：运行评测，分析失败样本，调整 prompt 或工具调用策略。&lt;/li&gt;
&lt;li&gt;技术债清理：围绕明确规则逐步替换旧写法，并保持行为不变。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些任务的共同点是：中间状态很多，失败原因不一定一次能看清，完成标准必须依赖验证结果。&lt;/p&gt;
&lt;h2 id=&#34;哪些任务不适合只靠-goal&#34;&gt;哪些任务不适合只靠 Goal
&lt;/h2&gt;&lt;p&gt;Goal 并不是万能的。下面这些任务如果只靠一个长提示词，风险会很高：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;目标非常模糊，例如“把产品增长做好”。&lt;/li&gt;
&lt;li&gt;周期很长，例如连续几周的 SEO、GEO、广告投放优化。&lt;/li&gt;
&lt;li&gt;需要跨系统调度，例如同时处理内容、数据、投放、客服和业务指标。&lt;/li&gt;
&lt;li&gt;涉及生产风险，例如数据库变更、线上配置、财务操作、账号权限调整。&lt;/li&gt;
&lt;li&gt;缺少验证手段，例如没有测试、没有指标、没有日志、没有人工验收标准。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这类任务更像 Mission，而不是 Goal。&lt;/p&gt;
&lt;p&gt;Goal 适合小时级到一两天的深度执行。Mission 则需要状态、历史、调度、人类审批、阶段性复盘和长期指标。比如 SEO / GEO / Ads 优化，不能只是让 Agent 循环写内容或调参数，还要持续记录策略、实验、数据变化和下一步计划。&lt;/p&gt;
&lt;h2 id=&#34;写好-goal-prompt-的模板&#34;&gt;写好 Goal Prompt 的模板
&lt;/h2&gt;&lt;p&gt;一个好用的 Goal prompt，至少应该包含下面几块内容：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;目标：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;用一句话说明最终要达成什么结果。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;背景：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;说明当前问题、相关文件、业务约束、已有尝试。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;范围：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;允许修改哪些目录、文件、模块；哪些地方不要碰。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;完成标准：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;列出可验证的 definition of done。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;验证命令：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;写清楚需要运行的测试、lint、build、eval 或脚本。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;失败策略：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;如果无法完成，要求 Agent 输出失败原因、已尝试方案、剩余阻塞点。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;风险边界：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;禁止破坏性操作，生产配置、密钥、数据库、外部服务需要人工确认。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;交付格式：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;要求总结修改点、验证结果、风险和后续建议。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;真正决定长任务效果的，往往不是 prompt 写得多漂亮，而是完成标准是否足够明确、足够可验证。&lt;/p&gt;
&lt;h2 id=&#34;goal-buddy-的价值先帮你把任务说清楚&#34;&gt;Goal Buddy 的价值：先帮你把任务说清楚
&lt;/h2&gt;&lt;p&gt;很多长任务失败，不是因为 Agent 能力不够，而是因为人类一开始没有把任务拆清楚。&lt;/p&gt;
&lt;p&gt;Goal Buddy 这类辅助工具的价值在于：在正式把任务交给 Agent 之前，先帮你准备目标、边界、完成标准和验证方式。它像一个任务预检器，会追问：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这个任务的最终可见结果是什么？&lt;/li&gt;
&lt;li&gt;哪些目录可以改，哪些不能改？&lt;/li&gt;
&lt;li&gt;成功后跑什么命令证明？&lt;/li&gt;
&lt;li&gt;失败时要不要继续尝试，最多尝试到什么程度？&lt;/li&gt;
&lt;li&gt;是否需要分阶段提交？&lt;/li&gt;
&lt;li&gt;哪些操作必须让人类确认？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这一步看似啰嗦，但它能显著减少 Agent 中途跑偏、过早停止，或改出一堆难以复核的代码的概率。&lt;/p&gt;
&lt;h2 id=&#34;给-codexclaude-codeopencode-用户的实践建议&#34;&gt;给 Codex、Claude Code、OpenCode 用户的实践建议
&lt;/h2&gt;&lt;p&gt;如果你正在用 Codex、Claude Code、OpenCode、OpenClaw 或类似编程 Agent，可以按下面方式处理长任务：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先提交当前工作区，保证有干净回滚点。&lt;/li&gt;
&lt;li&gt;把任务写成 Goal，而不是一句泛泛的需求。&lt;/li&gt;
&lt;li&gt;明确允许修改的范围和禁止修改的范围。&lt;/li&gt;
&lt;li&gt;给出验证命令，最好让 Agent 每一轮都能自己运行。&lt;/li&gt;
&lt;li&gt;要求 Agent 在无法完成时报告阻塞点，而不是硬编一个“完成”。&lt;/li&gt;
&lt;li&gt;对高风险操作设置人工确认，例如删除文件、改数据库、改部署配置。&lt;/li&gt;
&lt;li&gt;最后只接受带有测试结果和修改总结的交付。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;长任务 Agent 的正确使用方式，不是“让它自己随便干一晚上”，而是给它一个清楚的目标、坚实的护栏，以及可验证的出口。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;Codex Goal / Persistent Goals 的意义在于，把编程 Agent 从“执行一句指令”推进到“围绕一个目标持续工作”。&lt;/p&gt;
&lt;p&gt;它最适合复杂但边界明确的工程任务：迁移、重构、测试修复、依赖升级、评测优化。它不适合完全模糊、周期很长、缺少验证标准的业务任务；那些更应该设计成 Mission 系统。&lt;/p&gt;
&lt;p&gt;未来 AI Agent 的竞争点，很可能不只是模型会不会写代码，而是能不能围绕目标持续推进、正确判断停止时机，并把过程留给人类复核。&lt;/p&gt;
&lt;p&gt;参考：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.bilibili.com/video/BV1a3LF6fE2D/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Codex Goal 深度解析：让 AI Agent 连续工作数小时，不再提前摆烂&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://openai.com/index/introducing-the-codex-app/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Introducing the Codex app&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Ollama 接入 Codex App：本地大模型如何变成 AI 编程 Agent</title>
        <link>https://knightli.com/2026/05/26/ollama-codex-app-local-ai-coding-agent/</link>
        <pubDate>Tue, 26 May 2026 23:35:01 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/26/ollama-codex-app-local-ai-coding-agent/</guid>
        <description>&lt;p&gt;Ollama 最近把本地大模型和 AI 编程工具之间的距离又拉近了一步：通过 &lt;code&gt;ollama launch codex-app&lt;/code&gt;，用户可以把 Codex App 接到 Ollama 管理的本地或云端模型上。&lt;/p&gt;
&lt;p&gt;这件事的意义不只是“换一个模型后端”。它更像是把本地大模型从聊天窗口推到开发工作流里：模型不再只是回答问题，而是可以进入代码项目、理解文件结构、辅助修改代码、运行任务，成为 AI 编程 Agent 的一部分。&lt;/p&gt;
&lt;h2 id=&#34;先澄清这不是-openai-全功能永久免费&#34;&gt;先澄清：这不是 OpenAI 全功能永久免费
&lt;/h2&gt;&lt;p&gt;网上很多说法会把这件事概括成“Codex 免费了”。这个说法容易误解。&lt;/p&gt;
&lt;p&gt;更准确的理解是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Codex App 是 OpenAI 的 AI 编程工具；&lt;/li&gt;
&lt;li&gt;Ollama Launch 可以帮助 Codex App 使用 Ollama 模型；&lt;/li&gt;
&lt;li&gt;模型可以是本地模型，也可以是 Ollama 的云端模型；&lt;/li&gt;
&lt;li&gt;如果使用本地模型，推理成本主要变成自己的硬件、电费和时间，而不是按 API token 计费；&lt;/li&gt;
&lt;li&gt;Codex App、OpenAI 账号权益、不同模型可用性和官方限制，仍然要以 OpenAI 与 Ollama 的当前规则为准。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以它不是“所有 Codex 能力都永久免费”，而是多了一条本地化路线：让 AI 编程 Agent 可以不完全依赖 OpenAI API、Claude API 或 Gemini API。&lt;/p&gt;
&lt;h2 id=&#34;ollama-launch-codex-app-做了什么&#34;&gt;&lt;code&gt;ollama launch codex-app&lt;/code&gt; 做了什么？
&lt;/h2&gt;&lt;p&gt;Ollama 官方文档里，Codex App 的接入命令很简单：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ollama launch codex-app
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果想指定模型，可以写成：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ollama launch codex-app --model gpt-oss:120b
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;也可以只生成配置，不马上启动：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ollama launch codex-app --config
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果想恢复原来的 Codex 配置：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ollama launch codex-app --restore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;它的价值在于减少手动配置成本。过去要让一个 AI 编程工具接入本地模型，经常要自己改环境变量、OpenAI-compatible endpoint、&lt;code&gt;config.toml&lt;/code&gt;、模型名和 profile。现在 Ollama Launch 把这些步骤包装成一个更直接的流程。&lt;/p&gt;
&lt;h2 id=&#34;为什么本地模型接入-agent-很重要&#34;&gt;为什么本地模型接入 Agent 很重要？
&lt;/h2&gt;&lt;p&gt;以前本地大模型最常见的用法是聊天：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;写一段文案；&lt;/li&gt;
&lt;li&gt;回答一个问题；&lt;/li&gt;
&lt;li&gt;解释一段代码；&lt;/li&gt;
&lt;li&gt;做简单补全；&lt;/li&gt;
&lt;li&gt;总结文档。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些都很有用，但还停留在“问答工具”的层面。&lt;/p&gt;
&lt;p&gt;AI 编程 Agent 的区别在于，它面对的是一个真实项目。它需要读目录、看文件、理解报错、修改代码、运行命令、检查结果，再继续迭代。也就是说，它不是只输出答案，而是参与执行任务。&lt;/p&gt;
&lt;p&gt;当本地模型接入 Codex App、Claude Code、OpenCode、Aider、OpenHands 这类工具时，本地 AI 的角色就变了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以扫描项目结构；&lt;/li&gt;
&lt;li&gt;可以定位 Bug；&lt;/li&gt;
&lt;li&gt;可以改文件；&lt;/li&gt;
&lt;li&gt;可以生成新页面或小游戏；&lt;/li&gt;
&lt;li&gt;可以解释和重构代码；&lt;/li&gt;
&lt;li&gt;可以在开发循环里反复执行、验证、修正。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这也是本地大模型从“能聊”走向“能干活”的关键一步。&lt;/p&gt;
&lt;h2 id=&#34;本地-agent-的优势&#34;&gt;本地 Agent 的优势
&lt;/h2&gt;&lt;h3 id=&#34;1-成本更可控&#34;&gt;1. 成本更可控
&lt;/h3&gt;&lt;p&gt;大型项目很容易消耗大量 token。一次项目扫描、长上下文分析、多轮修复，放在云端模型上可能很快积累费用。&lt;/p&gt;
&lt;p&gt;本地模型虽然也有成本，比如显卡、内存、电费和时间，但它不会按 token 直接收费。对于大量试错、个人项目、离线实验，本地路线更适合慢慢折腾。&lt;/p&gt;
&lt;h3 id=&#34;2-可以离线工作&#34;&gt;2. 可以离线工作
&lt;/h3&gt;&lt;p&gt;如果模型、工具和依赖都已经在本机准备好，本地 Agent 在很多场景下可以断网继续工作。它可以读本地代码、分析项目、修改文件、生成页面或脚本。&lt;/p&gt;
&lt;p&gt;当然，涉及联网搜索、下载依赖、访问在线 API 的任务仍然需要网络。但基础代码分析和本地项目修改，不一定非要依赖云端模型。&lt;/p&gt;
&lt;h3 id=&#34;3-隐私边界更清楚&#34;&gt;3. 隐私边界更清楚
&lt;/h3&gt;&lt;p&gt;很多代码库、内部文档、实验项目并不适合直接发给云端模型。把模型放在本地，可以减少代码内容离开机器的机会。&lt;/p&gt;
&lt;p&gt;这不代表本地路线天然安全。Agent 仍然可能执行命令、改文件、访问敏感路径，所以权限、沙箱、Git diff review 仍然很重要。但至少在模型推理层面，本地化给了用户更多控制权。&lt;/p&gt;
&lt;h2 id=&#34;模型怎么选&#34;&gt;模型怎么选？
&lt;/h2&gt;&lt;p&gt;Ollama 的官方 &lt;code&gt;ollama launch&lt;/code&gt; 文档建议，代码类工具最好使用较大的上下文窗口，推荐至少 64K tokens。原因很简单：AI 编程任务经常需要同时读项目结构、多个文件、报错日志、需求说明和历史修改。&lt;/p&gt;
&lt;p&gt;本地模型可以从这些方向尝试：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;qwen3-coder&lt;/code&gt;：偏代码任务；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gpt-oss:20b&lt;/code&gt;：适合本地尝试；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;glm-4.7-flash&lt;/code&gt;：Ollama 官方推荐的 coding 模型之一；&lt;/li&gt;
&lt;li&gt;更大的云端模型：如果本地硬件不够，可以用 Ollama cloud 模型换取更完整上下文。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;中文场景下，Qwen 系列仍然值得优先尝试。它在中文理解、代码生成、推理和本地生态适配上都比较成熟。&lt;/p&gt;
&lt;h2 id=&#34;硬件门槛没有想象中那么高&#34;&gt;硬件门槛没有想象中那么高
&lt;/h2&gt;&lt;p&gt;很多人一提到 AI Agent，就默认需要 RTX 4090、24GB 显存、甚至企业级 GPU。&lt;/p&gt;
&lt;p&gt;实际情况更灵活。小模型、量化模型、MoE 模型、KV cache 量化和 CPU/GPU 混合 offload 让 6GB、8GB、12GB 显存机器也能做不少事情。&lt;/p&gt;
&lt;p&gt;当然，低显存机器不适合追求极致体验：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;速度会慢；&lt;/li&gt;
&lt;li&gt;上下文不能太大；&lt;/li&gt;
&lt;li&gt;大项目扫描会吃力；&lt;/li&gt;
&lt;li&gt;多并发基本不现实；&lt;/li&gt;
&lt;li&gt;模型质量和 100B+ 云端模型仍有差距。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但如果目标是个人项目、脚本修复、简单前端页面、小游戏、代码解释、离线实验，本地模型已经足够进入“可用”阶段。&lt;/p&gt;
&lt;h2 id=&#34;也可以用-llamacpp-接-openai-compatible-接口&#34;&gt;也可以用 llama.cpp 接 OpenAI-compatible 接口
&lt;/h2&gt;&lt;p&gt;除了 Ollama，另一条常见路线是用 &lt;code&gt;llama.cpp&lt;/code&gt; 的 &lt;code&gt;llama-server&lt;/code&gt; 提供本地 OpenAI-compatible API，再让 AI 编程工具连接到本地端口。&lt;/p&gt;
&lt;p&gt;一个典型的 &lt;code&gt;llama.cpp&lt;/code&gt; 启动命令类似这样：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bat&#34; data-lang=&#34;bat&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;llama-server.exe &lt;span class=&#34;se&#34;&gt;^
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt; &lt;/span&gt;-m &lt;span class=&#34;s2&#34;&gt;&amp;#34;models\Qwen3.6-27B-UD-Q5_K_XL.gguf&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;^
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt; &lt;/span&gt;-ngl 999 &lt;span class=&#34;se&#34;&gt;^
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt; &lt;/span&gt;-c 16384 &lt;span class=&#34;se&#34;&gt;^
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt; &lt;/span&gt;-n 2048 &lt;span class=&#34;se&#34;&gt;^
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt; &lt;/span&gt;-fa on &lt;span class=&#34;se&#34;&gt;^
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt; &lt;/span&gt;--jinja &lt;span class=&#34;se&#34;&gt;^
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt; &lt;/span&gt;--host 127.0.0.1 &lt;span class=&#34;se&#34;&gt;^
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt; &lt;/span&gt;--port 8080
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后在工具配置里把模型 provider 指向：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;model_providers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;llamacpp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;llama.cpp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;base_url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://127.0.0.1:8080/v1/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;wire_api&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;responses&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这条路线更灵活，但也更折腾。Ollama Launch 的优势是简单；&lt;code&gt;llama.cpp&lt;/code&gt; 的优势是可控参数更多，适合想细调显存、上下文、量化和推理后端的用户。&lt;/p&gt;
&lt;h2 id=&#34;使用本地-ai-agent-时要注意什么&#34;&gt;使用本地 AI Agent 时要注意什么？
&lt;/h2&gt;&lt;p&gt;本地不等于无风险。Agent 能改文件、跑命令、创建项目，就意味着它也可能误删文件、改错代码、执行不该执行的操作。&lt;/p&gt;
&lt;p&gt;建议：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在 Git 仓库里操作，确保随时能看 diff 和回滚。&lt;/li&gt;
&lt;li&gt;不要给 Agent 过大的系统权限。&lt;/li&gt;
&lt;li&gt;先在测试项目里试，不要直接扔生产代码库。&lt;/li&gt;
&lt;li&gt;重要文件修改前后都要人工 review。&lt;/li&gt;
&lt;li&gt;不要把密钥、账号、生产环境配置暴露给 Agent。&lt;/li&gt;
&lt;li&gt;本地模型能力有限，复杂架构决策不要完全交给它。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;把本地 Agent 当成“会执行任务的助手”，而不是“完全可靠的工程师”，体验会更健康。&lt;/p&gt;
&lt;h2 id=&#34;我的理解&#34;&gt;我的理解
&lt;/h2&gt;&lt;p&gt;Ollama 接入 Codex App 的意义在于，它把本地模型真正接进了 AI 编程工作流。&lt;/p&gt;
&lt;p&gt;过去，本地模型更多是一个聊天框；现在，它开始能进入项目、读代码、改文件、跑任务。这个变化会让很多普通开发者重新评估手里的电脑：也许不需要最贵的显卡，也能先搭起一个低成本、可离线、可控的 AI 编程环境。&lt;/p&gt;
&lt;p&gt;云端模型仍然强，特别是在复杂推理、大上下文、多模态和长任务稳定性上。但本地模型正在补上“执行工具”这一块。&lt;/p&gt;
&lt;p&gt;未来的 AI 编程，很可能不是纯云端或纯本地，而是混合形态：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;小任务、本地代码、隐私项目交给本地模型；&lt;/li&gt;
&lt;li&gt;高难推理、大上下文、跨系统任务交给云端模型；&lt;/li&gt;
&lt;li&gt;Ollama、Codex App、Claude Code、OpenCode 这类工具负责把两边接到同一个工作流里。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这才是本地 AI Agent 真正值得关注的地方。&lt;/p&gt;
&lt;h2 id=&#34;参考链接&#34;&gt;参考链接
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.freedidi.com/24310.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;零度博客：OpenAI Codex 彻底免费了！Ollama 接管 AI 编程 Agent，本地大模型开始自动干活！&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.ollama.com/integrations/codex-app&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Ollama 文档：Codex App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ollama.com/blog/launch&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Ollama Blog：ollama launch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://openai.com/index/introducing-the-codex-app/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenAI：Introducing the Codex app&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>oh-my-codex：给 Codex CLI 加上工作流、技能和运行时护栏</title>
        <link>https://knightli.com/2026/05/25/oh-my-codex-codex-cli-workflow-layer/</link>
        <pubDate>Mon, 25 May 2026 07:41:45 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/25/oh-my-codex-codex-cli-workflow-layer/</guid>
        <description>&lt;p&gt;&lt;code&gt;Yeachan-Heo/oh-my-codex&lt;/code&gt;，简称 OMX，是一个围绕 OpenAI Codex CLI 的工作流层。&lt;/p&gt;
&lt;p&gt;项目地址：&lt;a class=&#34;link&#34; href=&#34;https://github.com/Yeachan-Heo/oh-my-codex&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/Yeachan-Heo/oh-my-codex&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;它想解决的不是“再做一个新的 coding agent”，而是让已经在使用 Codex CLI 的人，有一套更稳定的日常工作方式：启动时带上项目指令，任务变复杂时先澄清再计划，执行时有 durable goal 和状态记录，收尾时用 review 和 QA 把结果压住。&lt;/p&gt;
&lt;p&gt;截至写作时，GitHub 页面显示仓库约有 29.4k star，最新 release 是 &lt;code&gt;v0.18.1&lt;/code&gt;，发布时间为 2026 年 5 月 21 日。README 也明确说，官方项目是 &lt;code&gt;Yeachan-Heo/oh-my-codex&lt;/code&gt;，官方 npm 包是 &lt;code&gt;oh-my-codex&lt;/code&gt;，不要把第三方 “OMX v2” 项目误认为这个仓库的官方延续。&lt;/p&gt;
&lt;h2 id=&#34;它到底是什么&#34;&gt;它到底是什么
&lt;/h2&gt;&lt;p&gt;OMX 不替代 Codex。&lt;/p&gt;
&lt;p&gt;它保留 Codex CLI 作为实际执行引擎，自己主要补三类东西：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;更固定的任务流程。&lt;/li&gt;
&lt;li&gt;可复用的 prompts、skills 和 specialist agents。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.omx/&lt;/code&gt; 目录下的计划、日志、状态和运行时记录。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;换句话说，Codex 负责“动手干活”，OMX 负责“让干活过程更像工程流程”。这也是它和普通 prompt 包最大的区别：它不是只往系统提示词里塞规则，而是把澄清、计划、执行、检查、团队协作和运行时诊断拆成一组可调用的工作面。&lt;/p&gt;
&lt;h2 id=&#34;推荐安装方式&#34;&gt;推荐安装方式
&lt;/h2&gt;&lt;p&gt;README 和 Getting Started 文档都强调：OMX 默认推荐在 macOS 或 Linux 上配合 Codex CLI 使用。原生 Windows 和 Codex App 不是它当前最主要的体验路径，可能会有不一致或不完整支持。&lt;/p&gt;
&lt;p&gt;如果你已经装好了 Codex CLI，可以这样开始：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex --version
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm install -g oh-my-codex
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;omx setup
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;omx doctor
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果你还没有 Codex CLI，并且希望 npm 管理安装：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm install -g @openai/codex
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm install -g oh-my-codex
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;omx setup
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;omx doctor
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里有一个细节：不要在已经由 Homebrew 管理 &lt;code&gt;codex&lt;/code&gt; 的机器上直接把 &lt;code&gt;@openai/codex&lt;/code&gt; 和 &lt;code&gt;oh-my-codex&lt;/code&gt; 合并成一个全局安装命令。README 提到，Homebrew 拥有的 &lt;code&gt;codex&lt;/code&gt; 二进制可能会和 npm 安装发生 &lt;code&gt;EEXIST&lt;/code&gt; 冲突。OMX 只需要一个可用、已登录、在 &lt;code&gt;PATH&lt;/code&gt; 上的 &lt;code&gt;codex&lt;/code&gt; 命令，并不要求 Codex 一定由 npm 安装。&lt;/p&gt;
&lt;p&gt;安装完成后，建议再跑一次真实执行烟测：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex login status
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;omx &lt;span class=&#34;nb&#34;&gt;exec&lt;/span&gt; --skip-git-repo-check -C . &lt;span class=&#34;s2&#34;&gt;&amp;#34;Reply with exactly OMX-EXEC-OK&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;omx doctor&lt;/code&gt; 只能证明本地安装结构大体正常，不能证明当前 shell/profile 里的 Codex 账号、代理、base URL 和认证链路真的能发起模型调用。这个区分很实际，尤其是你在不同 HOME、容器、远程环境或本地 OpenAI 兼容代理里切换时。&lt;/p&gt;
&lt;h2 id=&#34;默认工作流&#34;&gt;默认工作流
&lt;/h2&gt;&lt;p&gt;OMX 的主线工作流大致是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$deep-interview &amp;#34;clarify the authentication change&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ralplan &amp;#34;approve the auth plan and review tradeoffs&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$prometheus-strict &amp;#34;stress-test the plan before durable execution&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ultragoal &amp;#34;turn the approved plan into durable Codex goals&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其中最常用的是三步：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$deep-interview&lt;/code&gt;：在需求还不清楚时追问边界、目标和非目标。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ralplan&lt;/code&gt;：把需求整理成计划，并经过架构与批判视角确认。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ultragoal&lt;/code&gt;：把批准后的计划转成更耐跑的目标和检查点。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果任务需要并行协作，可以在 Ultragoal story 里用 &lt;code&gt;$team&lt;/code&gt;；如果只需要一个持续推进的单人循环，可以用 &lt;code&gt;$ralph&lt;/code&gt;。这套命名看起来有点重，但背后的想法很清楚：不要让 agent 一听到需求就急着改文件，而是先把“要做什么、怎么做、怎么验收、什么时候停”写清楚。&lt;/p&gt;
&lt;h2 id=&#34;skills-和-agents-提供了什么&#34;&gt;skills 和 agents 提供了什么
&lt;/h2&gt;&lt;p&gt;OMX 文档把技能分成几类。&lt;/p&gt;
&lt;p&gt;Canonical Workflow 里有 &lt;code&gt;$deep-interview&lt;/code&gt;、&lt;code&gt;$ralplan&lt;/code&gt;、&lt;code&gt;$prometheus-strict&lt;/code&gt;、&lt;code&gt;$ultragoal&lt;/code&gt;、&lt;code&gt;$code-review&lt;/code&gt; 和 &lt;code&gt;$ultraqa&lt;/code&gt;。这些面向的是完整工程任务：先澄清，再计划，再执行，再审查，再 QA。&lt;/p&gt;
&lt;p&gt;Execution Modes 里有 &lt;code&gt;$team&lt;/code&gt;、&lt;code&gt;$ralph&lt;/code&gt;、&lt;code&gt;$autopilot&lt;/code&gt;、&lt;code&gt;$ultrawork&lt;/code&gt; 等。它们决定任务是单线推进、团队并行，还是更强的自动循环。&lt;/p&gt;
&lt;p&gt;Agent Catalog 则更像角色库，包括 &lt;code&gt;analyst&lt;/code&gt;、&lt;code&gt;planner&lt;/code&gt;、&lt;code&gt;architect&lt;/code&gt;、&lt;code&gt;debugger&lt;/code&gt;、&lt;code&gt;executor&lt;/code&gt;、&lt;code&gt;verifier&lt;/code&gt;、&lt;code&gt;security-reviewer&lt;/code&gt;、&lt;code&gt;performance-reviewer&lt;/code&gt;、&lt;code&gt;code-reviewer&lt;/code&gt;、&lt;code&gt;test-engineer&lt;/code&gt;、&lt;code&gt;designer&lt;/code&gt;、&lt;code&gt;researcher&lt;/code&gt; 等。你不一定每天都要手动点名这些角色，但它们说明 OMX 的定位不是“万能大 prompt”，而是把工程过程拆成可复用的角色和阶段。&lt;/p&gt;
&lt;p&gt;这对长期项目有意义。AI 编程里很多失败不是模型完全不会写代码，而是它太快进入执行，跳过需求确认、架构边界、测试基线和收尾审查。OMX 试图用技能和角色把这些步骤固化下来。&lt;/p&gt;
&lt;h2 id=&#34;插件形态和运行时状态&#34;&gt;插件形态和运行时状态
&lt;/h2&gt;&lt;p&gt;README 提到，仓库里也包含官方 Codex plugin layout，路径是 &lt;code&gt;plugins/oh-my-codex&lt;/code&gt;，并带有 marketplace metadata。&lt;/p&gt;
&lt;p&gt;但文档也强调：这个插件形态不是 &lt;code&gt;npm install -g oh-my-codex&lt;/code&gt; 加 &lt;code&gt;omx setup&lt;/code&gt; 的替代品。插件作用更像是把 hooks、skill surface 和 Codex 生命周期集成包装起来，真正运行时仍然依赖已安装的 &lt;code&gt;omx&lt;/code&gt; CLI。&lt;/p&gt;
&lt;p&gt;最新 &lt;code&gt;v0.18.1&lt;/code&gt; release 的重点也集中在这条线上：插件安装会使用 pinned OMX launcher，hook 失败时更保守，Ultragoal 状态变更会序列化，release packaging 会排除 crate-local &lt;code&gt;.omx&lt;/code&gt; runtime cache，并同步 npm、Cargo workspace、lockfile 和插件 manifest 的版本号。&lt;/p&gt;
&lt;p&gt;这些变化说明 OMX 已经不只是一个 prompt 仓库，它开始认真处理安装形态、hook 安全、状态写入、release 包内容和跨运行时一致性。对工具链来说，这些都属于“不炫但很要命”的工程细节。&lt;/p&gt;
&lt;h2 id=&#34;适合谁&#34;&gt;适合谁
&lt;/h2&gt;&lt;p&gt;OMX 比较适合已经在认真使用 Codex CLI 的开发者，尤其是这些场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;经常让 Codex 处理多文件、多步骤任务。&lt;/li&gt;
&lt;li&gt;希望 agent 先澄清需求，而不是直接改代码。&lt;/li&gt;
&lt;li&gt;想把计划、执行、检查、review 和 QA 分开管理。&lt;/li&gt;
&lt;li&gt;需要在项目里保留 &lt;code&gt;.omx/&lt;/code&gt; 状态、计划和日志。&lt;/li&gt;
&lt;li&gt;想尝试 tmux/team runtime 或更强的长任务推进方式。&lt;/li&gt;
&lt;li&gt;团队愿意把自己的工程习惯沉淀成 skills 和 prompts。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你只是偶尔让 Codex 改一行配置、生成一个脚本、解释一段代码，OMX 可能会显得偏重。它更像是给高频 AI 编程用户准备的工具腰带，而不是新手必须安装的第一层入口。&lt;/p&gt;
&lt;h2 id=&#34;使用时要注意什么&#34;&gt;使用时要注意什么
&lt;/h2&gt;&lt;p&gt;第一，不要把 OMX 当成“无人值守自动完成一切”的保证。它能强化流程，但不能替你判断需求是否合理、架构是否该改、风险是否可接受。&lt;/p&gt;
&lt;p&gt;第二，平台边界要看清楚。README 现在明确推荐 macOS/Linux + Codex CLI。Windows 原生路径存在，但不是默认最佳体验。如果你在 Windows 上使用，WSL2 通常比原生终端更稳。&lt;/p&gt;
&lt;p&gt;第三，&lt;code&gt;omx doctor&lt;/code&gt; 不是最终验收。真正能证明环境可用的是 &lt;code&gt;codex login status&lt;/code&gt; 加 &lt;code&gt;omx exec&lt;/code&gt; 这种实际模型调用测试。&lt;/p&gt;
&lt;p&gt;第四，流程越强，越需要你写清楚任务边界。&lt;code&gt;$ultragoal&lt;/code&gt;、&lt;code&gt;$team&lt;/code&gt;、&lt;code&gt;$autopilot&lt;/code&gt; 这类能力适合有验收标准的任务。如果需求本身还很含糊，应该先用 &lt;code&gt;$deep-interview&lt;/code&gt; 或普通对话把边界拉清楚。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;oh-my-codex 的价值不在于让 Codex “变成另一个工具”，而在于给 Codex CLI 加了一层更工程化的工作方式。&lt;/p&gt;
&lt;p&gt;它把 AI 编程从“我说一句，你改一轮”往“澄清、计划、执行、检查、记录状态”推进了一步。对轻量任务来说，这可能有点重；但对经常用 Codex 做真实项目的人来说，稳定流程、可复用技能、运行时诊断和 durable goal 反而是省心的关键。&lt;/p&gt;
&lt;p&gt;如果你已经把 Codex CLI 当成日常开发工具，OMX 值得试一下。即使不直接安装，它对 skills、agents、计划和验收流程的拆法，也很适合拿来改造自己的 AI 编程工作流。&lt;/p&gt;
&lt;h2 id=&#34;参考资料&#34;&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Yeachan-Heo/oh-my-codex：&lt;a class=&#34;link&#34; href=&#34;https://github.com/Yeachan-Heo/oh-my-codex&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/Yeachan-Heo/oh-my-codex&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Getting Started：&lt;a class=&#34;link&#34; href=&#34;https://github.com/Yeachan-Heo/oh-my-codex/blob/main/docs/getting-started.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/Yeachan-Heo/oh-my-codex/blob/main/docs/getting-started.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Agent Catalog：&lt;a class=&#34;link&#34; href=&#34;https://github.com/Yeachan-Heo/oh-my-codex/blob/main/docs/agents.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/Yeachan-Heo/oh-my-codex/blob/main/docs/agents.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Skills Reference：&lt;a class=&#34;link&#34; href=&#34;https://github.com/Yeachan-Heo/oh-my-codex/blob/main/docs/skills.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/Yeachan-Heo/oh-my-codex/blob/main/docs/skills.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;v0.18.1 release：&lt;a class=&#34;link&#34; href=&#34;https://github.com/Yeachan-Heo/oh-my-codex/releases/tag/v0.18.1&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/Yeachan-Heo/oh-my-codex/releases/tag/v0.18.1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>OpenAI Symphony 是什么？Codex 编排、Issue 驱动与 AI Agent 开发工作流</title>
        <link>https://knightli.com/2026/05/25/openai-codex-orchestration-symphony/</link>
        <pubDate>Mon, 25 May 2026 00:17:32 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/25/openai-codex-orchestration-symphony/</guid>
        <description>&lt;p&gt;OpenAI 最近开源了一个很有意思的 Codex 编排规范：&lt;strong&gt;Symphony&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;它不是另一个聊天式编程助手，也不是一个完整的新 IDE。更准确地说，Symphony 是一套面向 Codex 的“工作编排方式”：把类似 Linear 的 issue tracker 变成编程智能体的控制平面，让每一个未关闭的任务都能对应一个持续运行的 Agent。&lt;/p&gt;
&lt;p&gt;官方文章里有一句话很能概括它的方向：过去工程师要同时盯着多个 Codex 会话，不断分配任务、审查输出、纠偏和重启；Symphony 想解决的，正是这个上下文切换瓶颈。&lt;/p&gt;
&lt;h2 id=&#34;symphony-解决的不是写代码而是管理-agent&#34;&gt;Symphony 解决的不是写代码，而是管理 Agent
&lt;/h2&gt;&lt;p&gt;单个 Codex 会话适合交互式开发：你给它一个任务，它修改代码，你 review，再继续追问。但当团队开始同时使用多个 Agent 时，问题会从“代码能不能写出来”变成“谁在做哪件事、做到哪一步、失败后谁来接手”。&lt;/p&gt;
&lt;p&gt;OpenAI 的做法是把工作重心从“会话”切到“任务”：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;issue 是真正的工作单元；&lt;/li&gt;
&lt;li&gt;每个未关闭 issue 都可以映射到一个独立 Agent 工作空间；&lt;/li&gt;
&lt;li&gt;Symphony 负责持续轮询任务看板，决定哪些任务需要启动、重试、停止或回收；&lt;/li&gt;
&lt;li&gt;Codex 在工作空间里执行实现、测试、提交、创建 PR、更新状态等动作；&lt;/li&gt;
&lt;li&gt;人类不再微操每个会话，而是审查结果、调整目标和维护边界。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这背后的变化很关键：Agent 不再只是一个被人类临时唤起的工具，而是开发流程里持续运行的一类执行者。&lt;/p&gt;
&lt;h2 id=&#34;为什么是-issue-tracker&#34;&gt;为什么是 issue tracker？
&lt;/h2&gt;&lt;p&gt;因为团队已经用 issue tracker 管理真实工作。&lt;/p&gt;
&lt;p&gt;需求、bug、重构、迁移、调研、优先级、阻塞关系、负责人、里程碑，这些信息本来就沉淀在 Linear、GitHub Issues 或类似系统里。Symphony 没有重新发明一个庞大的控制台，而是把这些现有系统当作 Agent 的任务入口。&lt;/p&gt;
&lt;p&gt;这样做有几个好处：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;工作不必从 issue 复制到聊天窗口里。&lt;/li&gt;
&lt;li&gt;人类可以继续按熟悉的方式创建、拆分、排期和关闭任务。&lt;/li&gt;
&lt;li&gt;Agent 的状态变化能回写到同一个工作系统里，方便团队异步协作。&lt;/li&gt;
&lt;li&gt;任务依赖可以自然形成 DAG，让未阻塞的任务并行推进。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果把传统 CI 看成“代码提交后的自动化”，Symphony 更像是“issue 创建后的自动化”。&lt;/p&gt;
&lt;h2 id=&#34;它的核心工作流&#34;&gt;它的核心工作流
&lt;/h2&gt;&lt;p&gt;一个典型的 Symphony 流程可以理解为：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;创建 issue
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -&amp;gt; Symphony 轮询到可执行任务
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -&amp;gt; 为该 issue 创建独立 workspace
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -&amp;gt; 启动 Codex agent session
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -&amp;gt; Agent 阅读任务、修改代码、运行测试
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -&amp;gt; 创建或更新 PR
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -&amp;gt; 写回任务状态、评论、证据和交付物
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -&amp;gt; 人类 review、合并或要求修改
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;官方规范里还强调了几个工程化点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个 issue 使用独立工作空间，降低相互污染；&lt;/li&gt;
&lt;li&gt;编排器维护重试、并发和恢复状态；&lt;/li&gt;
&lt;li&gt;工作流策略放在仓库内的 &lt;code&gt;WORKFLOW.md&lt;/code&gt;，让团队把 Agent 应该如何处理任务写成可版本化的规则；&lt;/li&gt;
&lt;li&gt;实现需要保留可观测性，至少要有结构化日志；&lt;/li&gt;
&lt;li&gt;成功状态不一定是 &lt;code&gt;Done&lt;/code&gt;，也可以是交给人类 review 的中间状态。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这说明 Symphony 不是简单地“让 AI 自动写代码”，而是在定义一套可运行、可恢复、可审计的 Agent 工作系统。&lt;/p&gt;
&lt;h2 id=&#34;目标驱动而不是死板状态机&#34;&gt;目标驱动，而不是死板状态机
&lt;/h2&gt;&lt;p&gt;OpenAI 在文章里提到一个重要转变：早期他们尝试把很多动作写死在外层 harness 里，例如提交代码、跑测试、处理 GitHub 流程。但随着 Codex 能力增强，这种方式反而限制了 Agent。&lt;/p&gt;
&lt;p&gt;后来的方向是给 Agent 设定目标，而不是把每一步都写成固定状态转换。&lt;/p&gt;
&lt;p&gt;比如，一个任务的目标可以是“完成 Vite 迁移并确保 CI 通过”。Agent 可以自己判断是否需要改配置、修测试、读 CI 日志、处理 review feedback，甚至拆出新的后续 issue。Symphony 负责提供边界、上下文和运行框架，而不是替 Agent 规定每一个动作。&lt;/p&gt;
&lt;p&gt;这也是它和传统自动化脚本的区别：脚本擅长重复确定流程；Symphony 面向的是带有不确定性的工程任务。&lt;/p&gt;
&lt;h2 id=&#34;和普通-codex-使用方式有什么不同&#34;&gt;和普通 Codex 使用方式有什么不同？
&lt;/h2&gt;&lt;p&gt;普通 Codex 会话更像“人带着 AI 写代码”：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;人类打开会话；&lt;/li&gt;
&lt;li&gt;人类描述任务；&lt;/li&gt;
&lt;li&gt;人类观察输出；&lt;/li&gt;
&lt;li&gt;人类随时纠偏；&lt;/li&gt;
&lt;li&gt;任务结束后再开下一个会话。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Symphony 更像“团队把任务池交给一组 Agent 执行”：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;人类写清楚 issue；&lt;/li&gt;
&lt;li&gt;系统持续发现可执行任务；&lt;/li&gt;
&lt;li&gt;Agent 在独立环境里推进；&lt;/li&gt;
&lt;li&gt;结果以 PR、评论、测试状态、视频或分析报告的形式返回；&lt;/li&gt;
&lt;li&gt;人类在关键节点做 review。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这不是替代工程师，而是把工程师从“同时照看多个会话”的负担里解放出来。OpenAI 在官方文章中提到，在部分团队中，合并到主分支的 PR 数量有明显提升；但更值得注意的是工作方式的变化：试验一个想法、发起一次重构、验证一个假设的启动成本变低了。&lt;/p&gt;
&lt;h2 id=&#34;适合哪些场景&#34;&gt;适合哪些场景？
&lt;/h2&gt;&lt;p&gt;Symphony 更适合这些任务：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;常规功能实现；&lt;/li&gt;
&lt;li&gt;已有代码库里的小型重构；&lt;/li&gt;
&lt;li&gt;基础设施迁移；&lt;/li&gt;
&lt;li&gt;依赖升级；&lt;/li&gt;
&lt;li&gt;测试补齐；&lt;/li&gt;
&lt;li&gt;CI 修复；&lt;/li&gt;
&lt;li&gt;调研后生成实现计划；&lt;/li&gt;
&lt;li&gt;根据 review feedback 继续修改 PR。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它不一定适合高度模糊、需要强业务判断或架构拍板的任务。对这类问题，交互式 Codex 会话仍然更自然，因为人类需要在过程中持续参与。&lt;/p&gt;
&lt;h2 id=&#34;风险和边界&#34;&gt;风险和边界
&lt;/h2&gt;&lt;p&gt;Symphony 的吸引力很强，但真正落地时不能只看“自动化”这一面。&lt;/p&gt;
&lt;p&gt;几个边界要提前想清楚：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;issue 必须写清楚，否则 Agent 会把模糊需求放大成错误实现；&lt;/li&gt;
&lt;li&gt;Agent 的权限要收敛，尤其是仓库、密钥、生产环境和第三方服务访问；&lt;/li&gt;
&lt;li&gt;每个工作空间要隔离，避免多个任务相互污染；&lt;/li&gt;
&lt;li&gt;CI、测试、lint 和 review 仍然是必须的质量门；&lt;/li&gt;
&lt;li&gt;任务状态、PR 链接、日志和失败原因要可追踪；&lt;/li&gt;
&lt;li&gt;人类 review 不能省，尤其是涉及安全、计费、数据迁移和权限逻辑的改动。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;官方仓库也把 Symphony 定位为 trusted environment 里的工程预览和参考实现，而不是一个拿来就能无脑替代研发流程的成品平台。&lt;/p&gt;
&lt;h2 id=&#34;我对-symphony-的理解&#34;&gt;我对 Symphony 的理解
&lt;/h2&gt;&lt;p&gt;Symphony 最有价值的地方，不在于它用了 Linear，也不在于参考实现选择了 Elixir，而在于它重新定义了编程 Agent 的入口。&lt;/p&gt;
&lt;p&gt;过去我们习惯从聊天窗口启动 AI 编程：这很灵活，但规模一大，人类注意力就成了瓶颈。Symphony 把入口放回 issue tracker，让 Agent 围绕真实任务持续工作。这样一来，AI 编程从“个人效率工具”开始向“团队工作流基础设施”靠近。&lt;/p&gt;
&lt;p&gt;如果你已经在使用 Codex、Claude Code、Cursor Agent 或类似工具，Symphony 值得关注的不是某个具体实现，而是它背后的模式：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;不要只管理 Agent 会话，要管理需要完成的工作。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这可能会成为下一阶段 AI 编程工具的关键分水岭。&lt;/p&gt;
&lt;h2 id=&#34;参考链接&#34;&gt;参考链接
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://openai.com/zh-Hans-CN/index/open-source-codex-orchestration-symphony/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Codex 编排的开源规范：Symphony&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/openai/symphony&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;openai/symphony&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>CLIProxyAPI：把 Codex、Claude Code、Gemini CLI 统一封装成 API</title>
        <link>https://knightli.com/2026/05/24/cliproxyapi-cli-to-api-gateway/</link>
        <pubDate>Sun, 24 May 2026 10:03:33 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/24/cliproxyapi-cli-to-api-gateway/</guid>
        <description>&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/router-for-me/CLIProxyAPI&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;CLIProxyAPI&lt;/a&gt; 是一个很有“民间工程味”的项目：它不是再造一个大模型，也不是单纯做 API 转发，而是把一堆原本偏交互式、偏 CLI、偏 OAuth 登录的 AI 工具，重新包成统一 API 服务。&lt;/p&gt;
&lt;p&gt;它支持的对象包括 Gemini CLI、OpenAI Codex、Claude Code、Amp CLI、AI Studio Build，以及上游 OpenAI 兼容服务。换句话说，它想解决的问题是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我手上有 CLI 工具、有订阅账号、有 OAuth 登录态，能不能像调用普通 API 一样，把这些能力接到自己的客户端、脚本、IDE 或内部服务里？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;CLIProxyAPI 给出的答案是：可以，中间加一层代理，把不同来源的 CLI 能力转换成 OpenAI、Gemini、Claude、Codex 兼容接口。&lt;/p&gt;
&lt;h2 id=&#34;它真正解决的痛点&#34;&gt;它真正解决的痛点
&lt;/h2&gt;&lt;p&gt;很多 AI 编程工具的能力本来很强，但默认使用方式并不适合自动化。&lt;/p&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gemini CLI 能登录账号使用，但你的程序更习惯调用 HTTP API。&lt;/li&gt;
&lt;li&gt;Claude Code 很适合交互式编码，但接入其他客户端时会遇到协议不一致。&lt;/li&gt;
&lt;li&gt;Codex CLI 支持 OAuth 登录和 Responses 风格能力，但不是所有上层工具都知道怎么和它说话。&lt;/li&gt;
&lt;li&gt;一个团队可能有多个账号，需要轮询、负载均衡、异常账号剔除和配额观察。&lt;/li&gt;
&lt;li&gt;你想让某些工具只认 OpenAI 格式，但后端实际可能是 Gemini、Claude 或 Codex。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CLIProxyAPI 的定位，就是做这些工具和客户端之间的“协议适配层”。&lt;/p&gt;
&lt;p&gt;它把复杂的一侧藏在后面：OAuth、CLI 登录、多账号、不同协议、不同 provider。前面则暴露相对熟悉的接口，比如 OpenAI Chat Completions、OpenAI Responses、Gemini、Claude Messages、Codex 相关端点。&lt;/p&gt;
&lt;h2 id=&#34;能力概览&#34;&gt;能力概览
&lt;/h2&gt;&lt;p&gt;从官方 README 和文档看，CLIProxyAPI 目前的核心能力包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;为 CLI 模型提供 OpenAI、Gemini、Claude、Codex 兼容 API 端点。&lt;/li&gt;
&lt;li&gt;通过 OAuth 登录接入 OpenAI Codex 和 Claude Code。&lt;/li&gt;
&lt;li&gt;支持流式、非流式响应，以及部分场景下的 WebSocket。&lt;/li&gt;
&lt;li&gt;支持函数调用、工具调用和多模态输入。&lt;/li&gt;
&lt;li&gt;支持 Gemini、OpenAI、Claude 多账号轮询与负载均衡。&lt;/li&gt;
&lt;li&gt;支持 Gemini AI Studio API Key。&lt;/li&gt;
&lt;li&gt;支持 AI Studio Build、Gemini CLI、Claude Code、OpenAI Codex 的多账号池。&lt;/li&gt;
&lt;li&gt;可以通过配置接入 OpenAI 兼容上游，比如 OpenRouter。&lt;/li&gt;
&lt;li&gt;提供 Go SDK，方便把代理能力嵌入到自己的服务里。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这类项目最有价值的地方，不是“多支持几个模型名”，而是把账号登录、协议转换和请求路由这些琐碎工作打包起来。&lt;/p&gt;
&lt;h2 id=&#34;它适合谁用&#34;&gt;它适合谁用
&lt;/h2&gt;&lt;p&gt;CLIProxyAPI 更适合下面几类人：&lt;/p&gt;
&lt;p&gt;第一类是重度 AI 编程用户。你已经在用 Codex、Claude Code、Gemini CLI，但想把它们接到 Cursor、Cline、RooCode、Amp、内部脚本或自建工作流里。&lt;/p&gt;
&lt;p&gt;第二类是有多账号池的人。比如你有多个 Gemini、OpenAI、Claude 登录态，不想手工切换，希望自动轮询、均衡使用、遇到异常账号时能快速排查。&lt;/p&gt;
&lt;p&gt;第三类是做团队内部网关的人。团队不希望每个客户端都分别适配 Gemini、Claude、Codex，而是想通过一个中间层统一暴露 API。&lt;/p&gt;
&lt;p&gt;第四类是喜欢折腾协议的人。你可能关心 Responses、Chat Completions、Claude Messages、Gemini v1beta 这些接口如何互相转换，也可能希望在同一套客户端里切换不同后端。&lt;/p&gt;
&lt;p&gt;如果只是个人偶尔问几句 AI，或者只用官方 App 聊天，那 CLIProxyAPI 的部署和维护成本就显得重了。&lt;/p&gt;
&lt;h2 id=&#34;和普通-api-中转有什么不同&#34;&gt;和普通 API 中转有什么不同
&lt;/h2&gt;&lt;p&gt;普通 API 中转服务一般是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;客户端 -&amp;gt; 中转 API -&amp;gt; 上游模型 API
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;CLIProxyAPI 的链路更像：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;客户端 -&amp;gt; CLIProxyAPI -&amp;gt; CLI / OAuth 登录态 / 多账号池 -&amp;gt; 模型服务
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;区别在于，它处理的不只是 API Key 转发，还包括 CLI 工具、OAuth 账号、协议表面和模型别名。&lt;/p&gt;
&lt;p&gt;比如 Codex 和 Claude Code 这类工具，本身就不是传统意义上“拿一个 API Key 就能稳定调用”的模式。CLIProxyAPI 把这些登录态和调用逻辑包装起来，让外部客户端像调用 API 一样访问它们。&lt;/p&gt;
&lt;p&gt;这也是它吸引人的地方，同时也是它复杂的地方。&lt;/p&gt;
&lt;h2 id=&#34;使用时最容易误解的地方&#34;&gt;使用时最容易误解的地方
&lt;/h2&gt;&lt;p&gt;第一，不要以为统一 &lt;code&gt;/v1/...&lt;/code&gt; 就能解决所有协议差异。&lt;/p&gt;
&lt;p&gt;CLIProxyAPI 文档里专门提醒过：当你需要某一类后端的请求和响应形态时，优先使用 provider-specific 路径。例如 messages 风格用 &lt;code&gt;/api/provider/{provider}/v1/messages&lt;/code&gt;，Gemini 模型路径用 &lt;code&gt;/api/provider/{provider}/v1beta/models/...&lt;/code&gt;，chat-completions 风格用 &lt;code&gt;/api/provider/{provider}/v1/chat/completions&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;统一入口方便，但不同协议的语义并不会凭空消失。工具调用、流式返回、多模态输入、系统消息处理，都可能因为后端不同而有细节差异。&lt;/p&gt;
&lt;p&gt;第二，模型名不等于唯一后端。&lt;/p&gt;
&lt;p&gt;如果多个后端暴露了相同的客户端可见模型名，仅靠路径不一定能锁定真正执行推理的那个后端。要严格固定后端，最好使用唯一 alias、前缀，或者避免让多个后端暴露同名模型。&lt;/p&gt;
&lt;p&gt;第三，多账号轮询不是无限额度。&lt;/p&gt;
&lt;p&gt;轮询只能更均匀地使用账号池，不能绕过上游服务的真实限制。账号异常、配额耗尽、风控、OAuth 失效，都需要单独监控。&lt;/p&gt;
&lt;p&gt;第四，它不是免维护魔法盒。&lt;/p&gt;
&lt;p&gt;一旦你把它放进日常工作流，就要关心配置、日志、上游账号状态、版本升级、客户端兼容性和安全边界。&lt;/p&gt;
&lt;h2 id=&#34;管理和监控怎么办&#34;&gt;管理和监控怎么办
&lt;/h2&gt;&lt;p&gt;官方 README 提到，从 v6.10.0 开始，CLIProxyAPI 和 CPAMC 不再预置数据统计功能。如果需要使用量统计，可以配合独立项目：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CPA Usage Keeper：同步 CLIProxyAPI 数据，存到 SQLite，并提供聚合 API 和仪表盘。&lt;/li&gt;
&lt;li&gt;CLIProxyAPI Usage Dashboard：本地优先的用量与配额看板，可展示账号、模型、时间窗口和 Codex 配额余量。&lt;/li&gt;
&lt;li&gt;CPA-Manager：更完整的管理中心，面向请求监控、费用估算、账号池巡检、异常账号定位和清理建议。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这说明 CLIProxyAPI 的核心更偏“代理和协议层”，而不是一站式商业管理后台。如果是团队使用，最好一开始就把日志、监控和账号池管理考虑进去。&lt;/p&gt;
&lt;h2 id=&#34;一个比较合理的使用姿势&#34;&gt;一个比较合理的使用姿势
&lt;/h2&gt;&lt;p&gt;如果要试用，可以按这个顺序来：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先用官方文档的 Quick Start 跑起来。&lt;/li&gt;
&lt;li&gt;只接一个 provider，比如 Gemini CLI 或 Codex，确认基本请求能通。&lt;/li&gt;
&lt;li&gt;再测试流式响应、工具调用、多模态输入这些高风险能力。&lt;/li&gt;
&lt;li&gt;确认客户端实际使用的是哪个 endpoint，不要混用协议路径。&lt;/li&gt;
&lt;li&gt;最后再加入多账号轮询、管理面板和用量统计。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;不要一上来就把 Gemini、Codex、Claude、OpenRouter、多账号和所有客户端全接进去。这样出错时很难判断是认证问题、协议问题、模型名问题，还是上游账号问题。&lt;/p&gt;
&lt;h2 id=&#34;安全边界也要想清楚&#34;&gt;安全边界也要想清楚
&lt;/h2&gt;&lt;p&gt;CLIProxyAPI 会接触到账号登录态、API Key、OAuth 相关凭据和请求内容。它如果只跑在自己机器上，风险相对可控；如果暴露到公网或团队内网，就必须认真处理认证、访问控制、日志脱敏和网络隔离。&lt;/p&gt;
&lt;p&gt;尤其是管理端点，最好只允许本机或可信内网访问。不要为了省事直接把管理接口裸露出去。&lt;/p&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结
&lt;/h2&gt;&lt;p&gt;CLIProxyAPI 的价值在于，它把原本散落在多个 CLI、多个账号、多个协议里的 AI 能力，收拢成一个可编程的 API 层。&lt;/p&gt;
&lt;p&gt;它适合重度 AI 编程用户、多账号用户和团队内部网关场景；不太适合只想“开箱即用、完全无维护”的轻量用户。&lt;/p&gt;
&lt;p&gt;如果你正在折腾 Codex、Claude Code、Gemini CLI 这些工具，并且希望把它们接进自己的客户端或自动化工作流里，CLIProxyAPI 值得认真看一眼。但要把它当基础设施来用，而不是当一次性小工具来用。&lt;/p&gt;
&lt;p&gt;参考资料：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/router-for-me/CLIProxyAPI&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;router-for-me/CLIProxyAPI GitHub 仓库&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/router-for-me/CLIProxyAPI/blob/main/README_CN.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;CLIProxyAPI 中文 README&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://help.router-for.me/cn/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;CLIProxyAPI 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>让 Codex 使用 DeepSeek 模型的两种方法：本地网关和 OpenRouter BYOK</title>
        <link>https://knightli.com/2026/05/24/codex-deepseek-config-ccx-openrouter-byok/</link>
        <pubDate>Sun, 24 May 2026 09:52:55 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/24/codex-deepseek-config-ccx-openrouter-byok/</guid>
        <description>&lt;p&gt;想让 Codex 使用 DeepSeek，第一反应通常是改 &lt;code&gt;~/.codex/config.toml&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek-chat&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;base_url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://api.deepseek.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个思路在一些旧版本或普通 OpenAI SDK 场景里确实成立，但放到当前 Codex CLI 上，很容易撞到一个底层问题：Codex 的自定义模型供应商走的是 OpenAI Responses 协议，而 DeepSeek 官方接口主要提供 OpenAI 兼容的 Chat Completions 调用方式。&lt;/p&gt;
&lt;p&gt;我本机当前是 &lt;code&gt;codex-cli 0.111.0&lt;/code&gt;。&lt;code&gt;codex --help&lt;/code&gt; 里可以看到它支持 &lt;code&gt;--config&lt;/code&gt;、&lt;code&gt;--model&lt;/code&gt;、&lt;code&gt;--profile&lt;/code&gt; 这些配置入口；OpenAI 官方 Codex 配置参考也写得很明确：&lt;code&gt;model_providers.&amp;lt;id&amp;gt;.wire_api&lt;/code&gt; 目前只支持 &lt;code&gt;responses&lt;/code&gt;，省略时也默认是 &lt;code&gt;responses&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;DeepSeek 官方文档则给出的调用路径是 &lt;code&gt;https://api.deepseek.com/chat/completions&lt;/code&gt;，示例也是 &lt;code&gt;client.chat.completions.create(...)&lt;/code&gt;。所以问题不在于 DeepSeek 不能被 OpenAI SDK 调用，而在于 Codex 发出去的请求语义和 DeepSeek 原生接口能理解的语义不完全是一套东西。&lt;/p&gt;
&lt;p&gt;这就是为什么直接把 &lt;code&gt;base_url&lt;/code&gt; 改成 &lt;code&gt;https://api.deepseek.com&lt;/code&gt; 后，可能出现下面这些现象：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;请求路径不匹配，直接 404 或返回格式不对。&lt;/li&gt;
&lt;li&gt;多轮对话、工具调用、补丁生成时解析失败。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tool_calls&lt;/code&gt; 顺序、消息结构、流式事件格式对不上。&lt;/li&gt;
&lt;li&gt;看起来模型能回一句话，但一到 Codex 真正干活就开始报错。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更稳的办法，是在 Codex 和 DeepSeek 之间放一个“翻译层”。常见有两种路线。&lt;/p&gt;
&lt;h2 id=&#34;方法一用本地网关桥接-deepseek&#34;&gt;方法一：用本地网关桥接 DeepSeek
&lt;/h2&gt;&lt;p&gt;本地网关的作用不是简单转发，而是把 Codex 侧的 Responses 风格请求，转换成 DeepSeek 能处理的 Chat Completions 风格请求，再把 DeepSeek 的结果转换回 Codex 能吃的格式。&lt;/p&gt;
&lt;p&gt;如果你用的是 ccx 一类本地网关，配置思路大致是这样：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;profiles&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;deepseek-ccx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek-v4-flash&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model_provider&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ccx-bridge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;model_providers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ccx-bridge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Local CCX Gateway&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;base_url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://localhost:3000/v1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;env_key&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;DEEPSEEK_API_KEY&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后在终端里设置 DeepSeek Key，再用这个 profile 启动：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;DEEPSEEK_API_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;your-deepseek-key&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex --profile deepseek-ccx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;PowerShell 里是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$env:DEEPSEEK_API_KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;your-deepseek-key&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;codex&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-profile&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;deepseek-ccx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里有两个细节要注意。&lt;/p&gt;
&lt;p&gt;第一，&lt;code&gt;base_url&lt;/code&gt; 要指向网关暴露给 Codex 的地址，不是 DeepSeek 官方地址。网关背后再去调用 DeepSeek。&lt;/p&gt;
&lt;p&gt;第二，&lt;code&gt;env_key&lt;/code&gt; 写什么取决于网关怎么鉴权。有的网关直接读取 DeepSeek 官方 Key，有的网关会要求你给它一个本地代理 Key，再由网关自己的后台保存 DeepSeek Key。遇到这种情况，&lt;code&gt;env_key&lt;/code&gt; 就应该改成网关要求的环境变量名。&lt;/p&gt;
&lt;p&gt;这条路的优点是本地可控，延迟和成本也更容易算清楚。缺点是你必须确认网关真的支持 Codex 当前使用的 Responses 语义，而不是只做了普通 Chat Completions 代理。&lt;/p&gt;
&lt;h2 id=&#34;方法二用-openrouter-byok-做线上桥接&#34;&gt;方法二：用 OpenRouter BYOK 做线上桥接
&lt;/h2&gt;&lt;p&gt;如果不想在本地部署网关，可以考虑 OpenRouter 的 BYOK。BYOK 的意思是把你自己的上游供应商 Key 绑定到 OpenRouter，由 OpenRouter 负责路由和转发。&lt;/p&gt;
&lt;p&gt;这里最容易写错的是环境变量。Codex 访问的是 OpenRouter，所以 &lt;code&gt;env_key&lt;/code&gt; 通常应该是 &lt;code&gt;OPENROUTER_API_KEY&lt;/code&gt;，不是 &lt;code&gt;DEEPSEEK_API_KEY&lt;/code&gt;。DeepSeek Key 要在 OpenRouter 的 BYOK 或 provider key 设置里添加。&lt;/p&gt;
&lt;p&gt;配置示例：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;profiles&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;deepseek-openrouter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek/deepseek-chat&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model_provider&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;openrouter&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;model_providers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;openrouter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;OpenRouter&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;base_url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://openrouter.ai/api/v1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;env_key&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;OPENROUTER_API_KEY&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;启动方式：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;your-openrouter-key&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex --profile deepseek-openrouter
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;PowerShell：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$env:OPENROUTER_API_KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;your-openrouter-key&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;codex&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-profile&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;deepseek-openrouter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后在 OpenRouter 后台把 DeepSeek 的 provider key 加进去。OpenRouter 的 BYOK 文档说明，绑定的 provider key 会被加密保存，并用于路由到对应供应商。&lt;/p&gt;
&lt;p&gt;这条路的优点是省掉本地网关维护成本，配置起来更像普通第三方 API 代理。缺点是中间多了一层线上服务，排障时要同时看 Codex、OpenRouter、DeepSeek 三边的错误信息。&lt;/p&gt;
&lt;h2 id=&#34;要不要继续用-deepseek-chat-这个模型名&#34;&gt;要不要继续用 deepseek-chat 这个模型名？
&lt;/h2&gt;&lt;p&gt;DeepSeek 官方文档在 2026 年 5 月的说明里，推荐模型名已经出现 &lt;code&gt;deepseek-v4-flash&lt;/code&gt; 和 &lt;code&gt;deepseek-v4-pro&lt;/code&gt;，并提示 &lt;code&gt;deepseek-chat&lt;/code&gt;、&lt;code&gt;deepseek-reasoner&lt;/code&gt; 兼容别名会在 2026-07-24 之后废弃。&lt;/p&gt;
&lt;p&gt;所以新配置里更建议优先测试：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek-v4-flash&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果走 OpenRouter，则要按 OpenRouter 的模型命名来写，例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek/deepseek-chat&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;实际可用名称以你所用网关或 OpenRouter 模型页为准。模型名不对时，错误通常会表现为 &lt;code&gt;model not found&lt;/code&gt;、404，或者 provider 找不到对应 endpoint。&lt;/p&gt;
&lt;h2 id=&#34;直接改-deepseek-官方-base_url-为什么不推荐&#34;&gt;直接改 DeepSeek 官方 base_url 为什么不推荐
&lt;/h2&gt;&lt;p&gt;你当然可以试着写：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;profiles&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;deepseek-direct&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek-v4-flash&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model_provider&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;model_providers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;deepseek&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;DeepSeek&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;base_url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://api.deepseek.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;env_key&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;DEEPSEEK_API_KEY&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;但这更像排错实验，不适合作为稳定方案。因为 Codex 会按 Responses 协议去和自定义 provider 说话，而 DeepSeek 官方示例走的是 &lt;code&gt;/chat/completions&lt;/code&gt;。如果 DeepSeek 或 Codex 未来补齐了兼容层，这种直连才可能变得简单；在此之前，桥接层更靠谱。&lt;/p&gt;
&lt;h2 id=&#34;改完配置后还是走-openai-怎么办&#34;&gt;改完配置后还是走 OpenAI 怎么办
&lt;/h2&gt;&lt;p&gt;先确认配置文件位置。全局配置应该在：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;~/.codex/config.toml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;项目里的 &lt;code&gt;.codex/config.toml&lt;/code&gt; 不适合放 &lt;code&gt;model_provider&lt;/code&gt;、&lt;code&gt;model_providers&lt;/code&gt; 这类机器级 provider 配置。OpenAI 官方文档也提醒，项目级配置不会覆盖这些本地 provider 和认证相关字段。&lt;/p&gt;
&lt;p&gt;如果 Codex 仍然要求网页登录，或者看起来还在走默认 OpenAI 模型，可以先退出当前登录态：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex &lt;span class=&#34;nb&#34;&gt;logout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;有些旧教程会写成交互界面里的 &lt;code&gt;/logout&lt;/code&gt;。在当前 CLI 里，更稳的是直接在终端执行 &lt;code&gt;codex logout&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;还可以用临时参数做一次快速验证：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex --profile deepseek-ccx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;或者：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex -c &lt;span class=&#34;nv&#34;&gt;model_provider&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;ccx-bridge -c &lt;span class=&#34;nv&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;deepseek-v4-flash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果这样能生效，说明配置本身可读；如果不生效，优先检查 profile 名称、TOML 语法、环境变量是否只在当前 shell 里有效。&lt;/p&gt;
&lt;h2 id=&#34;排障清单&#34;&gt;排障清单
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;401&lt;/code&gt;：Key 不对，或者 &lt;code&gt;env_key&lt;/code&gt; 指向了错误的环境变量。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;404&lt;/code&gt;：&lt;code&gt;base_url&lt;/code&gt; 或模型名不对，也可能是把 Responses 请求打到了只支持 Chat Completions 的地址。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tool_calls&lt;/code&gt;、patch、流式解析报错：大概率是协议桥接不完整。&lt;/li&gt;
&lt;li&gt;仍然提示登录 OpenAI：执行 &lt;code&gt;codex logout&lt;/code&gt;，再确认是否用了正确 profile。&lt;/li&gt;
&lt;li&gt;PowerShell 设置环境变量后新开窗口失效：&lt;code&gt;$env:...&lt;/code&gt; 只对当前会话生效，需要长期保存就改用户环境变量。&lt;/li&gt;
&lt;li&gt;OpenRouter BYOK 没走自己的 DeepSeek Key：检查 OpenRouter 后台 provider key 是否绑定、是否允许当前 OpenRouter API Key 使用，以及是否开启了 fallback。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;结论&#34;&gt;结论
&lt;/h2&gt;&lt;p&gt;让 Codex 使用 DeepSeek，不是不能改 &lt;code&gt;config.toml&lt;/code&gt;，而是不能只改 &lt;code&gt;base_url&lt;/code&gt; 就指望一切自动兼容。&lt;/p&gt;
&lt;p&gt;当前更稳的两条路是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用本地网关做协议桥接，Codex 连本地网关，网关再连 DeepSeek。&lt;/li&gt;
&lt;li&gt;用 OpenRouter BYOK 做线上转发，Codex 连 OpenRouter，DeepSeek Key 绑定在 OpenRouter 后台。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果只是想快速试用，OpenRouter 路线更省事；如果你希望 Key、成本、日志都尽量掌握在自己手里，本地网关更适合长期折腾。&lt;/p&gt;
&lt;p&gt;参考资料：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://developers.openai.com/codex/config-reference/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenAI Codex Configuration Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://api-docs.deepseek.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;DeepSeek API Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://openrouter.ai/docs/use-cases/byok/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenRouter BYOK Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>CodeGraph 是什么？给 Claude Code、Codex 和 Cursor 加一个本地代码地图</title>
        <link>https://knightli.com/2026/05/23/codegraph-local-code-knowledge-graph-ai-coding-agent/</link>
        <pubDate>Sat, 23 May 2026 21:09:46 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/23/codegraph-local-code-knowledge-graph-ai-coding-agent/</guid>
        <description>&lt;p&gt;&lt;code&gt;CodeGraph&lt;/code&gt; 是一个给 AI 编程工具使用的本地代码知识图谱。它会提前给项目建立索引，把符号关系、调用图、代码结构、路由关系等信息整理成可查询的图，让 Claude Code、Codex CLI、Cursor、OpenCode、Hermes Agent 这类工具不用每次都靠 grep、glob、Read 和子代理到处翻文件。&lt;/p&gt;
&lt;p&gt;它解决的是一个很实际的问题：AI Agent 看大型代码库时，很多成本不是花在真正修改代码上，而是花在“找代码在哪里”。如果每次都重新搜索、读取、筛选，token、时间和工具调用都会被消耗掉。&lt;code&gt;CodeGraph&lt;/code&gt; 的思路是先把代码库变成一张本地地图，让 Agent 先问地图，再决定要不要读具体文件。&lt;/p&gt;
&lt;h2 id=&#34;它主要解决什么痛点&#34;&gt;它主要解决什么痛点
&lt;/h2&gt;&lt;p&gt;AI 编程工具在小项目里通常还好，文件少，搜索快，读一遍也不贵。但项目一大，常见问题就会出现：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Agent 为了理解一个模块，反复调用 grep、find、ls、Read。&lt;/li&gt;
&lt;li&gt;探索子代理读了很多无关文件，主任务上下文却没有变清楚。&lt;/li&gt;
&lt;li&gt;问一个架构问题时，token 大量花在定位文件上。&lt;/li&gt;
&lt;li&gt;改一个函数前，不知道谁在调用它、它又调用了谁。&lt;/li&gt;
&lt;li&gt;Web 项目里，URL 路由和实际处理函数之间的关系不够直观。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;CodeGraph&lt;/code&gt; 试图把这些“先找路”的工作前置。项目索引建好后，Agent 可以直接查询相关符号、调用方、被调用方、影响范围和代码片段。&lt;/p&gt;
&lt;h2 id=&#34;安装方式&#34;&gt;安装方式
&lt;/h2&gt;&lt;p&gt;项目提供跨平台安装脚本，不要求用户自己准备 Node.js：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Windows PowerShell 可以使用：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;irm &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;https&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;//&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;raw&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;githubusercontent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;com&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;colbymchenry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;codegraph&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;install&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;ps1&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;iex
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果已经有 Node 环境，也可以直接用 npm：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npx @colbymchenry/codegraph
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;或者全局安装：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm i -g @colbymchenry/codegraph
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;安装器会自动检测并配置已安装的 Agent，例如 Claude Code、Cursor、Codex CLI、opencode 和 Hermes Agent。它会写入对应的 MCP server 配置和指令文件，让这些工具知道什么时候调用 CodeGraph。&lt;/p&gt;
&lt;h2 id=&#34;初始化项目&#34;&gt;初始化项目
&lt;/h2&gt;&lt;p&gt;安装完成后，需要在目标项目里建立索引：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; your-project
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codegraph init -i
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个命令会生成项目级知识图谱索引。README 中提到，只要项目里存在 &lt;code&gt;.codegraph/&lt;/code&gt; 目录，Agent 就可以自动使用 CodeGraph 工具。&lt;/p&gt;
&lt;p&gt;如果不想继续使用，也可以卸载全局配置：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codegraph uninstall
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;它会移除安装器写入的 MCP server 配置、指令和权限。项目中的 &lt;code&gt;.codegraph/&lt;/code&gt; 索引不会被自动删除，如果要移除项目索引，需要使用 &lt;code&gt;codegraph uninit&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;为什么它对-agent-有用&#34;&gt;为什么它对 Agent 有用
&lt;/h2&gt;&lt;p&gt;Claude Code、Codex CLI、Cursor 这类工具在理解代码库时，常常会先做探索：找文件、读入口、查引用、再追调用链。这个过程对人来说像“翻项目”，对模型来说就是一串工具调用和上下文消耗。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CodeGraph&lt;/code&gt; 把这一步变成索引查询。Agent 可以先用 &lt;code&gt;codegraph_context&lt;/code&gt; 找到相关入口、符号和片段，再用 &lt;code&gt;codegraph_explore&lt;/code&gt; 或其他工具读取必要内容。这样做的好处是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;少读无关文件。&lt;/li&gt;
&lt;li&gt;少调用搜索工具。&lt;/li&gt;
&lt;li&gt;更快找到真正相关的代码。&lt;/li&gt;
&lt;li&gt;改动前更容易看清影响范围。&lt;/li&gt;
&lt;li&gt;大型仓库里的架构问题更容易回答。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;项目 README 给出的基准测试显示，在 7 个真实开源代码库上，对比启用 CodeGraph 和不启用 CodeGraph，平均结果是成本更低、token 更少、速度更快、工具调用更少。具体数字会受项目规模、语言、问题类型和 Agent 使用方式影响，但方向很清楚：越大的仓库，预索引的价值越明显。&lt;/p&gt;
&lt;h2 id=&#34;核心能力&#34;&gt;核心能力
&lt;/h2&gt;&lt;h3 id=&#34;1-智能上下文构建&#34;&gt;1. 智能上下文构建
&lt;/h3&gt;&lt;p&gt;一个工具调用可以返回入口点、相关符号和代码片段，减少 Agent 先派一堆探索任务再慢慢筛选的情况。对架构理解、模块定位、功能入口分析很有用。&lt;/p&gt;
&lt;h3 id=&#34;2-全文搜索&#34;&gt;2. 全文搜索
&lt;/h3&gt;&lt;p&gt;CodeGraph 使用 FTS5 做全文搜索，可以在整个代码库里快速按名称和文本查找代码。这不是替代所有 grep 场景，而是让 Agent 有一个更结构化的第一站。&lt;/p&gt;
&lt;h3 id=&#34;3-影响分析&#34;&gt;3. 影响分析
&lt;/h3&gt;&lt;p&gt;在改函数、类、方法或路由前，可以查询 callers、callees 和影响半径。对重构、修 bug、删除旧代码尤其有用，因为最怕的就是只改了当前文件，却漏掉上游或下游调用。&lt;/p&gt;
&lt;h3 id=&#34;4-自动保持新鲜&#34;&gt;4. 自动保持新鲜
&lt;/h3&gt;&lt;p&gt;README 中提到，CodeGraph 使用原生文件系统事件，例如 FSEvents、inotify、ReadDirectoryChangesW，并带有 debounce auto-sync。意思是索引会随着本地代码变化自动更新，不需要每改一个文件都手动重建。&lt;/p&gt;
&lt;h3 id=&#34;5-多语言支持&#34;&gt;5. 多语言支持
&lt;/h3&gt;&lt;p&gt;项目列出的支持范围超过 19 种语言，包括 TypeScript、JavaScript、Python、Go、Rust、Java、C#、PHP、Ruby、C、C++、Swift、Kotlin、Dart、Lua、Luau、Svelte、Liquid、Pascal / Delphi 等。&lt;/p&gt;
&lt;p&gt;这让它更适合多语言仓库和全栈项目，而不是只服务某一种语言。&lt;/p&gt;
&lt;h3 id=&#34;6-web-路由感知&#34;&gt;6. Web 路由感知
&lt;/h3&gt;&lt;p&gt;CodeGraph 还会识别多种 Web 框架里的路由文件和路由声明，把 URL pattern 和处理函数连接起来。README 中提到的框架包括 Django、Flask、FastAPI、Express、NestJS、Laravel、Rails、Spring、Gin、Axum、ASP.NET、Vapor、React Router、SvelteKit 等。&lt;/p&gt;
&lt;p&gt;这点很实用。很多 Web 项目的真实入口不是某个明显的 &lt;code&gt;main&lt;/code&gt; 函数，而是路由、controller、handler、view 或 resolver。Agent 如果能先知道 URL 到处理函数的关系，理解业务流程会快很多。&lt;/p&gt;
&lt;h2 id=&#34;本地优先的设计&#34;&gt;本地优先的设计
&lt;/h2&gt;&lt;p&gt;CodeGraph 强调 &lt;code&gt;100% local&lt;/code&gt;。它不需要 API key，不依赖外部服务，索引数据保存在本地 SQLite 数据库里。&lt;/p&gt;
&lt;p&gt;对企业项目、私有仓库或敏感代码来说，这个设计很重要。AI 工具接入代码库时，大家最担心的往往不是“能不能查到代码”，而是“代码结构和索引会不会被发出去”。CodeGraph 的定位是本地构建、本地查询、本地服务 Agent。&lt;/p&gt;
&lt;p&gt;当然，本地也意味着要考虑磁盘空间、索引时间、文件监听和项目规模。如果仓库特别大，第一次初始化和后续同步仍然需要资源。&lt;/p&gt;
&lt;h2 id=&#34;适合哪些场景&#34;&gt;适合哪些场景
&lt;/h2&gt;&lt;p&gt;CodeGraph 更适合这些场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;大型代码库，经常需要问架构和调用链问题。&lt;/li&gt;
&lt;li&gt;使用 Claude Code、Codex CLI、Cursor 等 Agent 做代码理解和修改。&lt;/li&gt;
&lt;li&gt;希望减少 Agent 到处读文件、乱搜、反复探索。&lt;/li&gt;
&lt;li&gt;需要在改动前分析影响范围。&lt;/li&gt;
&lt;li&gt;Web 项目路由复杂，需要快速从 URL 找到处理函数。&lt;/li&gt;
&lt;li&gt;团队希望给 AI Agent 一个更稳定的本地项目索引。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果只是几十个文件的小项目，普通搜索已经够快，CodeGraph 的优势可能不明显。它最有价值的地方，是中大型代码库和经常让 Agent 做探索的场景。&lt;/p&gt;
&lt;h2 id=&#34;使用时要注意什么&#34;&gt;使用时要注意什么
&lt;/h2&gt;&lt;p&gt;第一，CodeGraph 不是替代代码审查和测试的工具。它能帮助 Agent 更快找到相关代码，但不能保证 Agent 的修改一定正确。&lt;/p&gt;
&lt;p&gt;第二，索引质量会影响使用效果。项目结构复杂、生成代码很多、语言混杂或 build 产物没有排除时，索引可能会变得臃肿。使用前最好确认 &lt;code&gt;.gitignore&lt;/code&gt;、项目目录和索引范围是否合理。&lt;/p&gt;
&lt;p&gt;第三，MCP 配置和 Agent 指令很关键。README 里也提醒，CodeGraph 只有在被正确查询时才有帮助。如果 Agent 仍然绕开它去大量读文件，预索引就会变成额外开销。&lt;/p&gt;
&lt;p&gt;第四，虽然它是本地工具，也要注意权限。安装器会写入 Agent 配置和权限列表，团队环境中最好统一审查这些配置。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;CodeGraph&lt;/code&gt; 的价值可以简单理解为：给 AI Agent 一张本地代码地图。它不是让模型更聪明，而是让模型少迷路。&lt;/p&gt;
&lt;p&gt;当 Claude Code、Codex CLI、Cursor 这类工具面对大型仓库时，最耗费上下文的往往是探索过程。CodeGraph 用预索引的符号关系、调用图、路由图和全文搜索，把“找代码”这一步提前做好，让 Agent 把更多预算花在理解和修改上。&lt;/p&gt;
&lt;p&gt;如果你已经在真实项目里使用 AI 编程工具，并且经常遇到“它读了一堆文件还是没找到重点”的情况，CodeGraph 值得试一下。它代表了 AI 编程工具的一个重要方向：不只是换更强的模型，也要给模型更好的本地代码上下文。&lt;/p&gt;
&lt;p&gt;参考资料：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GitHub 项目：&lt;a class=&#34;link&#34; href=&#34;https://github.com/colbymchenry/codegraph&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/colbymchenry/codegraph&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Google I/O 之后，GPT 和 Gemini 订阅怎么选？普通用户与开发者对比</title>
        <link>https://knightli.com/2026/05/21/gpt-vs-gemini-subscription-after-google-io-2026/</link>
        <pubDate>Thu, 21 May 2026 08:33:14 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/21/gpt-vs-gemini-subscription-after-google-io-2026/</guid>
        <description>&lt;p&gt;Google I/O 2026 之后，很多人的 AI 订阅选择变复杂了。&lt;/p&gt;
&lt;p&gt;以前问题比较简单：写作、问答、编程、文件分析，大多数人优先看 ChatGPT；如果深度使用 Google 搜索、Android、Gmail、Docs、YouTube，再考虑 Gemini。现在不一样了。Google 在 I/O 上把 Gemini 3.5 Flash、Gemini Omni、Antigravity 2.0、Gemini API Managed Agents、Google AI Studio 和 AI Ultra 订阅一起推出来，Gemini 生态开始从“可选项”变成“强竞争主线”。&lt;/p&gt;
&lt;p&gt;这篇文章不做抽象模型跑分，而是回答一个实际问题：普通用户、开发者、内容创作者和企业用户，到底该订阅 GPT / ChatGPT，还是 Gemini / Google AI？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;注意：AI 订阅价格、额度、地区和模型可用性变化很快。本文写作时间是 2026 年 5 月 21 日，正式订阅前应以 OpenAI 与 Google 当前页面为准。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;先说结论&#34;&gt;先说结论
&lt;/h2&gt;&lt;p&gt;如果你只想选一个主力订阅，可以按这个逻辑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;日常写作、问答、文件分析、泛办公、中文英文混合使用：优先 ChatGPT Plus。&lt;/li&gt;
&lt;li&gt;高频编程、需要 Codex、复杂推理、项目级代码任务：优先 ChatGPT Plus / Pro，再按额度决定是否升级。&lt;/li&gt;
&lt;li&gt;深度使用 Google 生态、Gmail、Docs、Drive、Android、Search：优先 Gemini / Google AI Pro。&lt;/li&gt;
&lt;li&gt;重点做视频、AI 影像、Google Flow、YouTube Shorts、Gemini Omni：优先 Google AI Pro / Ultra。&lt;/li&gt;
&lt;li&gt;需要 Antigravity、Gemini API Managed Agents、AI Studio 到 Android 的工作流：重点看 Google AI Pro / Ultra。&lt;/li&gt;
&lt;li&gt;企业团队：不要只看个人订阅，重点看 Business / Enterprise、Workspace、权限、审计和数据边界。&lt;/li&gt;
&lt;li&gt;预算有限：一个主力付费订阅 + 另一个平台免费层或按量 API，通常比同时订两个高阶套餐更划算。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一句话：GPT 更像通用生产力和代码助手主力；Gemini 在 Google I/O 之后更像 Google 生态里的系统级 AI 套件。&lt;/p&gt;
&lt;h2 id=&#34;google-io-之后gemini-发生了什么变化&#34;&gt;Google I/O 之后，Gemini 发生了什么变化
&lt;/h2&gt;&lt;p&gt;Google I/O 2026 让 Gemini 的价值不再只取决于 Gemini App 本身。&lt;/p&gt;
&lt;p&gt;几个关键变化：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Gemini 3.5 Flash&lt;/code&gt;：Google 把它定位为从 prompt 到 action 的高速模型，面向真实 Agent 工作流。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Gemini Omni&lt;/code&gt;：从任意输入创作内容，当前重点从视频开始，支持多模态创作和自然语言多轮编辑。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Google Antigravity 2.0&lt;/code&gt;：Agent-first development platform，面向开发者的多 Agent 编排与编程平台。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Gemini API Managed Agents&lt;/code&gt;：通过 API 创建可推理、可用工具、可执行代码的托管 Agent。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Google AI Studio&lt;/code&gt;：从 prompt playground 走向移动端、Android 原生应用生成和 Antigravity 项目导出。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Google AI Ultra&lt;/code&gt;：I/O 后新增 $100/月档位，并面向开发者、技术负责人、知识工作者和高级创作者。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更重要的是，Google 把 Gemini App 的使用额度从传统每日 prompt 限制，转向 &lt;code&gt;compute-used&lt;/code&gt; 模型。复杂视频、代码和长上下文任务会消耗更多额度，简单文本任务消耗更少；额度每 5 小时刷新，直到达到周限制。&lt;/p&gt;
&lt;p&gt;这说明 Google 正在把 Gemini 订阅做成“模型 + 应用 + 创作 + 开发工具 + Google 生态”的打包入口。&lt;/p&gt;
&lt;h2 id=&#34;chatgpt--gpt-订阅现在适合谁&#34;&gt;ChatGPT / GPT 订阅现在适合谁
&lt;/h2&gt;&lt;p&gt;ChatGPT 的优势依然很强，尤其适合把 AI 当作日常工作主力的人。&lt;/p&gt;
&lt;p&gt;根据 OpenAI 当前价格页和帮助文档，ChatGPT Free 可以使用 GPT-5.5 Instant 等基础能力；Plus 提供 GPT-5.5 Thinking、更多消息和上传额度、更强图像生成、deep research、agent mode、项目、任务、自定义 GPT 和扩展 Codex 使用；Pro 则提供更高额度、GPT-5.5 Pro、更高 Codex 使用量、最大 deep research 和 agent mode。&lt;/p&gt;
&lt;p&gt;更适合 ChatGPT 的场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;写作、总结、翻译、改稿。&lt;/li&gt;
&lt;li&gt;复杂问答和结构化分析。&lt;/li&gt;
&lt;li&gt;文件上传、表格分析、研究报告。&lt;/li&gt;
&lt;li&gt;编程问答、代码审查、重构建议。&lt;/li&gt;
&lt;li&gt;使用 Codex 做代码库任务。&lt;/li&gt;
&lt;li&gt;多语言内容生产。&lt;/li&gt;
&lt;li&gt;对模型质量和回答稳定性要求高，但不强依赖 Google 产品。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你是普通用户，ChatGPT Plus 仍然是最稳的主力订阅。它覆盖面广，学习成本低，中文和英文任务都比较均衡。&lt;/p&gt;
&lt;p&gt;如果你是开发者，ChatGPT 的关键不只是聊天，而是 Codex。OpenAI 帮助文档说明，Codex 可随符合条件的 ChatGPT 计划使用，额度随计划不同而变化。也就是说，如果你大量使用 Codex 做代码修改、PR、重构、测试修复，订阅选择要把 Codex 额度一起算进去。&lt;/p&gt;
&lt;h2 id=&#34;gemini--google-ai-订阅现在适合谁&#34;&gt;Gemini / Google AI 订阅现在适合谁
&lt;/h2&gt;&lt;p&gt;Gemini 的优势在 Google I/O 之后更清晰：它和 Google 生态绑定更深。&lt;/p&gt;
&lt;p&gt;Google AI 订阅现在不只是 Gemini App 里的模型额度，还包括 Gemini Omni、Google Flow、Antigravity、AI Studio、部分 YouTube Premium / Lite 权益、Workspace / Android / Search 生态能力等。Google 官方还把 AI Ultra 扩成 $100 与更高阶档位，强调开发者、技术负责人、知识工作者和高级创作者。&lt;/p&gt;
&lt;p&gt;更适合 Gemini 的场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你深度使用 Gmail、Docs、Drive、Sheets、Slides、Android。&lt;/li&gt;
&lt;li&gt;你想把 AI 放进 Google Search、YouTube、Workspace 生态。&lt;/li&gt;
&lt;li&gt;你关注 Gemini Omni、Google Flow、视频生成和视频编辑。&lt;/li&gt;
&lt;li&gt;你想试 Antigravity、Gemini API Managed Agents、AI Studio mobile。&lt;/li&gt;
&lt;li&gt;你需要超长上下文文件理解。&lt;/li&gt;
&lt;li&gt;你做 Google 生态应用、Android 原生应用、Workspace 自动化。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Google 官方帮助页显示，Gemini Apps 的上下文窗口会随订阅提高：无 AI plan 为 32K，AI Plus 为 128K，AI Pro 和 AI Ultra 为 1 million。AI Pro / Ultra 也会提供更高使用限制、更多特性和部分早期功能。&lt;/p&gt;
&lt;p&gt;如果你的工作环境已经在 Google 生态里，Gemini 的价值会被放大。否则，单独把 Gemini 当作“另一个聊天机器人”来订阅，性价比就不一定比 ChatGPT 更稳。&lt;/p&gt;
&lt;h2 id=&#34;普通用户怎么选&#34;&gt;普通用户怎么选
&lt;/h2&gt;&lt;p&gt;普通用户最容易踩的坑，是因为新模型发布就同时订多个平台。&lt;/p&gt;
&lt;p&gt;更理性的选法是先看主场景。&lt;/p&gt;
&lt;p&gt;如果你主要做这些事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;写文章。&lt;/li&gt;
&lt;li&gt;查资料。&lt;/li&gt;
&lt;li&gt;做总结。&lt;/li&gt;
&lt;li&gt;读 PDF。&lt;/li&gt;
&lt;li&gt;写邮件。&lt;/li&gt;
&lt;li&gt;改简历。&lt;/li&gt;
&lt;li&gt;学习语言。&lt;/li&gt;
&lt;li&gt;日常问答。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;优先选 ChatGPT Plus。它的通用性更好，任务边界更清楚，不需要你深度绑定某个生态。&lt;/p&gt;
&lt;p&gt;如果你主要做这些事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gmail / Docs / Drive / YouTube / Android 高频使用。&lt;/li&gt;
&lt;li&gt;希望 AI 直接进入 Google 生态。&lt;/li&gt;
&lt;li&gt;想体验 Gemini App、Daily Brief、Google Search AI、YouTube 内容问答。&lt;/li&gt;
&lt;li&gt;需要长上下文读取 Google 文档。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;优先选 Google AI Pro。&lt;/p&gt;
&lt;p&gt;如果你只是轻量用户，两个平台都先用免费层，等明确遇到限制再付费。不要为了“可能用到”而订阅高阶套餐。&lt;/p&gt;
&lt;h2 id=&#34;开发者怎么选&#34;&gt;开发者怎么选
&lt;/h2&gt;&lt;p&gt;开发者要分两类。&lt;/p&gt;
&lt;p&gt;第一类是以代码问答、修 bug、写脚本、读代码库为主。优先看 ChatGPT Plus / Pro + Codex。&lt;/p&gt;
&lt;p&gt;理由是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Codex 和 ChatGPT 账号打通。&lt;/li&gt;
&lt;li&gt;ChatGPT 对代码解释、重构、测试、错误分析比较稳。&lt;/li&gt;
&lt;li&gt;Plus 已经覆盖很多日常开发任务。&lt;/li&gt;
&lt;li&gt;Pro 更适合高频、长时间、复杂代码库任务。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;第二类是面向 Google 生态、Agent 平台、Android、Workspace 或 Gemini API 开发。优先看 Google AI Pro / Ultra。&lt;/p&gt;
&lt;p&gt;理由是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gemini 3.5 Flash 是 Google I/O 后 Agent 工作流重点模型。&lt;/li&gt;
&lt;li&gt;Antigravity 2.0 是 Google 的 Agent-first 开发平台。&lt;/li&gt;
&lt;li&gt;Managed Agents 能通过 API 创建带工具和隔离 Linux 环境的 Agent。&lt;/li&gt;
&lt;li&gt;AI Studio 可以和 Android、Workspace、Antigravity 更自然衔接。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你是全栈开发者，最务实的组合通常是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ChatGPT Plus 作为日常代码与文档主力。&lt;/li&gt;
&lt;li&gt;Gemini 免费层或 AI Pro 用于 Google 生态、长上下文和视频/Agent 新能力。&lt;/li&gt;
&lt;li&gt;API 按量使用，不要把个人订阅误当生产 API 预算。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;内容创作者怎么选&#34;&gt;内容创作者怎么选
&lt;/h2&gt;&lt;p&gt;内容创作者的选择取决于你做什么内容。&lt;/p&gt;
&lt;p&gt;如果你主要做：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;文案。&lt;/li&gt;
&lt;li&gt;标题。&lt;/li&gt;
&lt;li&gt;脚本。&lt;/li&gt;
&lt;li&gt;文章。&lt;/li&gt;
&lt;li&gt;图文内容。&lt;/li&gt;
&lt;li&gt;资料整理。&lt;/li&gt;
&lt;li&gt;多语言改写。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ChatGPT Plus 依然很稳。&lt;/p&gt;
&lt;p&gt;如果你主要做：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;视频生成。&lt;/li&gt;
&lt;li&gt;短视频创意。&lt;/li&gt;
&lt;li&gt;AI 影像。&lt;/li&gt;
&lt;li&gt;YouTube Shorts。&lt;/li&gt;
&lt;li&gt;Google Flow 工作流。&lt;/li&gt;
&lt;li&gt;多模态素材整合。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Gemini / Google AI Pro 或 Ultra 更值得关注。I/O 之后，Gemini Omni 和 Google Flow 是 Google 在创作场景里的核心牌。&lt;/p&gt;
&lt;p&gt;如果预算有限，可以先订一个文本主力，再用另一个平台的免费层或短期订阅测试视频能力。视频模型的额度、排队、时长、分辨率和地区限制变化很快，不建议一开始就按长期生产服务规划。&lt;/p&gt;
&lt;h2 id=&#34;企业和团队怎么选&#34;&gt;企业和团队怎么选
&lt;/h2&gt;&lt;p&gt;企业不要按个人用户思路选。&lt;/p&gt;
&lt;p&gt;企业真正要看的不是“哪个模型这周更强”，而是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据是否用于训练。&lt;/li&gt;
&lt;li&gt;是否有 SSO、MFA、RBAC。&lt;/li&gt;
&lt;li&gt;是否有审计日志。&lt;/li&gt;
&lt;li&gt;是否支持内部知识连接。&lt;/li&gt;
&lt;li&gt;是否能控制插件、连接器和 Agent 权限。&lt;/li&gt;
&lt;li&gt;是否符合组织的合规要求。&lt;/li&gt;
&lt;li&gt;是否能和现有办公套件打通。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果企业已经重度使用 Google Workspace，Gemini 企业方案自然更值得评估。如果团队已经围绕 ChatGPT、Codex、OpenAI API 和内部工具链搭建流程，OpenAI Business / Enterprise 更自然。&lt;/p&gt;
&lt;p&gt;对工程团队来说，还要单独评估 Codex、Antigravity、Gemini API Managed Agents、MCP、CI/CD、代码权限、仓库访问和审计。&lt;/p&gt;
&lt;h2 id=&#34;什么时候需要-pro--ultra&#34;&gt;什么时候需要 Pro / Ultra
&lt;/h2&gt;&lt;p&gt;很多人其实不需要高阶档位。&lt;/p&gt;
&lt;p&gt;你需要 ChatGPT Pro 的典型信号：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每天长时间使用 ChatGPT。&lt;/li&gt;
&lt;li&gt;Plus 额度经常不够。&lt;/li&gt;
&lt;li&gt;高频使用 Codex。&lt;/li&gt;
&lt;li&gt;经常跑 deep research、agent mode、复杂推理。&lt;/li&gt;
&lt;li&gt;需要 GPT-5.5 Pro 这类更高阶模型。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你需要 Google AI Ultra 的典型信号：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;高频使用 Gemini、Flow、Antigravity。&lt;/li&gt;
&lt;li&gt;需要更高 Gemini / Antigravity 使用额度。&lt;/li&gt;
&lt;li&gt;做视频创作、AI 影像、长上下文研究。&lt;/li&gt;
&lt;li&gt;深度依赖 Google 生态和新功能优先体验。&lt;/li&gt;
&lt;li&gt;需要 Gemini Spark、Project Genie 或更高级订阅权益。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你只是每天问几次问题、偶尔写文章或改代码，Plus / Pro、AI Pro / Ultra 这类高阶档位可能都不是刚需。&lt;/p&gt;
&lt;h2 id=&#34;最省钱的订阅策略&#34;&gt;最省钱的订阅策略
&lt;/h2&gt;&lt;p&gt;更推荐这种组合：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先选一个主力付费订阅。&lt;/li&gt;
&lt;li&gt;另一个平台先用免费层。&lt;/li&gt;
&lt;li&gt;真正需要 API 时再按量付费。&lt;/li&gt;
&lt;li&gt;视频、Agent、深度研究类高消耗功能按月开关，不要全年盲订。&lt;/li&gt;
&lt;li&gt;每月复盘一次：本月有没有真的用满额度？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;几个常见组合：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;普通办公：ChatGPT Plus + Gemini 免费层。&lt;/li&gt;
&lt;li&gt;Google 生态用户：Google AI Pro + ChatGPT 免费层。&lt;/li&gt;
&lt;li&gt;开发者：ChatGPT Plus/Pro + Gemini API/AI Studio 按需。&lt;/li&gt;
&lt;li&gt;视频创作者：Google AI Pro/Ultra + ChatGPT 免费层或 Plus。&lt;/li&gt;
&lt;li&gt;企业团队：不要用个人套餐拼，直接评估 Business / Enterprise / Workspace 方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;订阅前检查清单&#34;&gt;订阅前检查清单
&lt;/h2&gt;&lt;p&gt;付费前先确认这些问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你的地区是否支持目标套餐？&lt;/li&gt;
&lt;li&gt;你要用的模型是否包含在该套餐里？&lt;/li&gt;
&lt;li&gt;Codex、Antigravity、Flow、Omni 是否真的可用？&lt;/li&gt;
&lt;li&gt;视频功能是否有地区、年龄、排队或分辨率限制？&lt;/li&gt;
&lt;li&gt;API 调用是否包含在订阅里，还是单独计费？&lt;/li&gt;
&lt;li&gt;文件上传、上下文窗口、agent mode、deep research 是否有额度限制？&lt;/li&gt;
&lt;li&gt;数据隐私设置是否符合你的项目要求？&lt;/li&gt;
&lt;li&gt;你是否已经有 Google One、Workspace、ChatGPT Business 或学校/公司账号权益？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;尤其要注意：个人订阅不等于 API 免费，不等于商用无限额度，也不等于企业合规。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;Google I/O 之后，Gemini 的竞争力明显增强，尤其是在视频、多模态、Google 生态、Android、AI Studio 和 Antigravity 方向。但 ChatGPT 仍然是更稳的通用主力，特别是在日常写作、复杂问答、文件分析、代码辅助和 Codex 工作流里。&lt;/p&gt;
&lt;p&gt;最简单的判断是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不知道选哪个：先选 ChatGPT Plus。&lt;/li&gt;
&lt;li&gt;深度 Google 用户：选 Google AI Pro。&lt;/li&gt;
&lt;li&gt;高频开发者：看 Codex 和 Antigravity 谁更贴近你的工作流。&lt;/li&gt;
&lt;li&gt;视频创作者：优先看 Gemini Omni、Flow 和 Google AI Pro / Ultra。&lt;/li&gt;
&lt;li&gt;企业用户：按合规、权限、审计和现有办公生态选，而不是按模型热度选。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI 订阅不是越多越好。真正划算的方式，是明确一个主力工作流，再把其他平台作为补充，而不是为每一个发布会都多开一个长期订阅。&lt;/p&gt;
&lt;p&gt;参考来源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://chatgpt.com/pricing/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenAI：ChatGPT Pricing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/11369540-using-codex-with-your-chatgpt-plan&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenAI Help：Using Codex with your ChatGPT plan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.google/products-and-platforms/products/google-one/google-ai-subscriptions/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Google Blog：Everything new in Google AI subscriptions from I/O 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.google/innovation-and-ai/technology/developers-tools/google-io-2026-developer-highlights/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Google Blog：I/O 2026 developer highlights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://support.google.com/gemini/answer/16275805&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Google Help：Gemini Apps limits and upgrades for Google AI subscribers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Graphify 解决 Claude Code 最大局限：把代码库变成 AI 可查询知识图谱</title>
        <link>https://knightli.com/2026/05/21/safishamsi-graphify-ai-code-knowledge-graph/</link>
        <pubDate>Thu, 21 May 2026 08:02:32 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/21/safishamsi-graphify-ai-code-knowledge-graph/</guid>
        <description>&lt;p&gt;&lt;code&gt;safishamsi/graphify&lt;/code&gt; 是一个面向 AI 编程助手的知识图谱工具。它的目标很直接：把一个项目目录里的代码、文档、SQL schema、脚本、论文、图片、视频和音频，整理成可查询的知识图谱，让 AI 助手不再只靠 &lt;code&gt;grep&lt;/code&gt;、全文阅读或临时搜索来理解项目。&lt;/p&gt;
&lt;p&gt;项目地址：&lt;a class=&#34;link&#34; href=&#34;https://github.com/safishamsi/graphify&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;safishamsi/graphify&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;截至本文整理时，GitHub 页面显示项目约有 50.2k stars、5.4k forks，许可证为 MIT。README 对它的描述是：在 AI 编程助手里输入 &lt;code&gt;/graphify&lt;/code&gt;，它就会把整个项目映射成一个可以查询的知识图谱。&lt;/p&gt;
&lt;h2 id=&#34;它解决的核心问题&#34;&gt;它解决的核心问题
&lt;/h2&gt;&lt;p&gt;AI 编程助手越来越强，但在真实代码库里仍然经常遇到几个问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不知道关键模块之间怎么连接。&lt;/li&gt;
&lt;li&gt;读了很多文件，但没形成整体架构地图。&lt;/li&gt;
&lt;li&gt;搜索命中了文本，却不知道上下游依赖。&lt;/li&gt;
&lt;li&gt;代码、数据库 schema、文档和基础设施配置分散在不同地方。&lt;/li&gt;
&lt;li&gt;多人协作时，每个人对项目结构的理解不一致。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Graphify 想做的是给项目生成一层“记忆层”。它把代码实体、文档概念、数据库表、配置、设计说明和跨文件关系连接起来，让 AI 助手可以按图谱查询，而不是每次从零开始扫文件。&lt;/p&gt;
&lt;h2 id=&#34;最小使用方式&#34;&gt;最小使用方式
&lt;/h2&gt;&lt;p&gt;Graphify 的最小用法非常简单。安装后，在 AI 编程助手里输入：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;在 PowerShell 里要注意，前导 &lt;code&gt;/&lt;/code&gt; 会被当成路径分隔符，所以 Windows PowerShell 下应使用：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;运行后会生成 &lt;code&gt;graphify-out/&lt;/code&gt; 目录，核心文件包括：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify-out/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── graph.html
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── GRAPH_REPORT.md
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└── graph.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这三个文件分工不同：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;graph.html&lt;/code&gt;：浏览器里打开的交互式图谱，可以点击节点、过滤和搜索。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GRAPH_REPORT.md&lt;/code&gt;：项目亮点、关键概念、意外连接和推荐问题。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;graph.json&lt;/code&gt;：完整图谱，后续可以直接查询，不必重新读所有文件。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果想生成更可读的架构页面和 Mermaid 调用流图，可以运行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify &lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; callflow-html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;安装和平台支持&#34;&gt;安装和平台支持
&lt;/h2&gt;&lt;p&gt;Graphify 的 PyPI 包名是 &lt;code&gt;graphifyy&lt;/code&gt;，注意是双 &lt;code&gt;y&lt;/code&gt;。README 特别提醒，PyPI 上其他 &lt;code&gt;graphify*&lt;/code&gt; 包并不属于该项目，但 CLI 命令仍然叫 &lt;code&gt;graphify&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;推荐安装方式是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv tool install graphifyy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;也可以使用：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pipx install graphifyy
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install graphifyy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;安装后注册到 AI 助手：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;项目支持的平台很多，包括 Claude Code、Codex、OpenCode、GitHub Copilot CLI、VS Code Copilot Chat、Aider、Cursor、Gemini CLI、Kimi Code、Kiro、Google Antigravity 等。不同平台可以用不同安装命令，例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify install --platform codex
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify install --platform gemini
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify cursor install
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify antigravity install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Codex 用户还需要在 &lt;code&gt;~/.codex/config.toml&lt;/code&gt; 的 &lt;code&gt;[features]&lt;/code&gt; 下加入：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;multi_agent&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;README 也说明，Codex 使用 &lt;code&gt;$graphify&lt;/code&gt;，不是 &lt;code&gt;/graphify&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;它能处理哪些文件&#34;&gt;它能处理哪些文件
&lt;/h2&gt;&lt;p&gt;Graphify 覆盖的输入类型很广。&lt;/p&gt;
&lt;p&gt;代码方面，它支持 31 种语言，包括 Python、TypeScript、JavaScript、Go、Rust、Java、C/C++、Ruby、C#、Kotlin、Scala、PHP、Swift、Lua、Zig、PowerShell、SQL、Shell、JSON 等。&lt;/p&gt;
&lt;p&gt;文档方面，它支持：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.mdx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.qmd&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.rst&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.yaml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.yml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;还可以通过可选依赖扩展更多类型：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[pdf]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[office]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[video]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[mcp]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[neo4j]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[sql]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[all]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其中，&lt;code&gt;pdf&lt;/code&gt; 用于 PDF 提取，&lt;code&gt;office&lt;/code&gt; 用于 &lt;code&gt;.docx&lt;/code&gt; 和 &lt;code&gt;.xlsx&lt;/code&gt;，&lt;code&gt;video&lt;/code&gt; 用于视频和音频转写，&lt;code&gt;mcp&lt;/code&gt; 用于 MCP stdio server，&lt;code&gt;neo4j&lt;/code&gt; 用于推送到 Neo4j，&lt;code&gt;sql&lt;/code&gt; 用于 SQL schema 提取。&lt;/p&gt;
&lt;h2 id=&#34;生成的报告有什么价值&#34;&gt;生成的报告有什么价值
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;GRAPH_REPORT.md&lt;/code&gt; 不是普通摘要，它会把项目里更值得 AI 助手关注的关系挑出来。&lt;/p&gt;
&lt;p&gt;README 里提到的报告内容包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;God nodes&lt;/code&gt;：项目里连接最多的核心概念。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Surprising connections&lt;/code&gt;：跨文件、跨模块的意外连接。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;The why&lt;/code&gt;：从注释、docstring、设计文档里提取出的设计理由。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Suggested questions&lt;/code&gt;：图谱特别适合回答的问题。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Confidence tags&lt;/code&gt;：关系会标记为 &lt;code&gt;EXTRACTED&lt;/code&gt;、&lt;code&gt;INFERRED&lt;/code&gt; 或 &lt;code&gt;AMBIGUOUS&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这点很关键。普通搜索只能告诉你“哪里出现了这个词”，而图谱可以回答“这个概念和哪些模块、配置、表、文档有关”。对大型代码库来说，这比单纯全文检索更接近架构理解。&lt;/p&gt;
&lt;h2 id=&#34;常用命令&#34;&gt;常用命令
&lt;/h2&gt;&lt;p&gt;Graphify 的常见命令包括：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify .
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify ./docs --update
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify . --cluster-only
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify . --no-viz
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify . --wiki
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify &lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; callflow-html
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify query &lt;span class=&#34;s2&#34;&gt;&amp;#34;what connects auth to the database?&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify path &lt;span class=&#34;s2&#34;&gt;&amp;#34;UserService&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;DatabasePool&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify explain &lt;span class=&#34;s2&#34;&gt;&amp;#34;RateLimiter&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;也可以把论文或视频加入图谱：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify add https://arxiv.org/abs/1706.03762
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify add &amp;lt;youtube-url&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果要做 PR 辅助分析，还可以使用：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify prs
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify prs &lt;span class=&#34;m&#34;&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify prs --triage
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify prs --conflicts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这类命令适合代码评审场景：看 PR 影响了哪些图谱社区、是否和其他 PR 有冲突风险、哪些 review queue 更值得优先处理。&lt;/p&gt;
&lt;h2 id=&#34;和-mcpneo4jci-的关系&#34;&gt;和 MCP、Neo4j、CI 的关系
&lt;/h2&gt;&lt;p&gt;Graphify 不只是生成 HTML 图。它也可以把图谱暴露给 AI 助手反复调用。&lt;/p&gt;
&lt;p&gt;例如可以启动 MCP server：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python -m graphify.serve graphify-out/graph.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;MCP server 提供的能力包括 &lt;code&gt;query_graph&lt;/code&gt;、&lt;code&gt;get_node&lt;/code&gt;、&lt;code&gt;get_neighbors&lt;/code&gt;、&lt;code&gt;shortest_path&lt;/code&gt;、&lt;code&gt;list_prs&lt;/code&gt;、&lt;code&gt;get_pr_impact&lt;/code&gt;、&lt;code&gt;triage_prs&lt;/code&gt; 等。&lt;/p&gt;
&lt;p&gt;它也支持 Neo4j 导出或推送：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify ./raw --neo4j
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify ./raw --neo4j-push bolt://localhost:7687
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;团队协作上，README 建议可以提交 &lt;code&gt;graphify-out/&lt;/code&gt;，让团队每个人拉取后都能共享同一份项目地图。还可以运行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify hook install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这样每次 git commit 后自动重建图谱，并设置 merge driver，避免 &lt;code&gt;graph.json&lt;/code&gt; 在多人并行提交时留下冲突标记。&lt;/p&gt;
&lt;h2 id=&#34;隐私和成本要怎么看&#34;&gt;隐私和成本要怎么看
&lt;/h2&gt;&lt;p&gt;Graphify 的 README 对隐私边界写得比较清楚。&lt;/p&gt;
&lt;p&gt;代码文件会通过 tree-sitter 在本地解析，不会发出 API 调用。视频和音频可以通过 faster-whisper 本地转写。文档、PDF、图片这类语义提取内容，则会通过你的 AI 助手模型 API 处理。&lt;/p&gt;
&lt;p&gt;如果用 headless &lt;code&gt;graphify extract&lt;/code&gt;，可能需要设置这些环境变量：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ANTHROPIC_API_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;GEMINI_API_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;GOOGLE_API_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;OPENAI_API_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;DEEPSEEK_API_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;MOONSHOT_API_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;OLLAMA_BASE_URL
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;本地 Ollama、AWS Bedrock、Claude Code CLI 等也可以作为 backend。README 还写明项目没有 telemetry、usage tracking 和 analytics。&lt;/p&gt;
&lt;p&gt;实际使用时要注意：代码本地解析不等于所有内容都不出网。涉及文档、PDF、图片或云端模型时，仍然要看 backend、API key、企业合规和数据边界。&lt;/p&gt;
&lt;h2 id=&#34;适合哪些场景&#34;&gt;适合哪些场景
&lt;/h2&gt;&lt;p&gt;Graphify 适合几类用户：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;想让 Claude Code、Codex、Cursor、Gemini CLI 更懂项目结构的开发者。&lt;/li&gt;
&lt;li&gt;需要快速理解大型陌生代码库的人。&lt;/li&gt;
&lt;li&gt;需要把代码、SQL schema、文档、配置放在一起分析的团队。&lt;/li&gt;
&lt;li&gt;做架构审查、PR review、重构影响分析的人。&lt;/li&gt;
&lt;li&gt;希望把项目知识暴露成 MCP 工具给 Agent 使用的人。&lt;/li&gt;
&lt;li&gt;想为团队保留“项目地图”的技术负责人。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它不一定适合所有项目。小型脚本、一次性 demo、结构非常简单的仓库，用普通搜索和 README 可能已经够用。Graphify 的价值更容易出现在模块多、文档多、团队协作多、AI 助手频繁参与开发的大项目里。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;Graphify 的意义在于，它把 AI 编程助手的上下文从“临时读取文件”推进到“长期可查询的项目知识图谱”。&lt;/p&gt;
&lt;p&gt;对开发者来说，它不是替代 IDE、搜索或 LSP，而是给 AI 助手补一层结构化记忆：哪些模块重要、哪些概念连接紧密、哪些文档解释了设计理由、某个 PR 会影响哪些社区。随着 Codex、Claude Code、Gemini CLI、Antigravity 这类 Agent 工具继续普及，这类“项目图谱层”会越来越有用。&lt;/p&gt;
&lt;p&gt;参考来源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/safishamsi/graphify&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub：safishamsi/graphify&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Scientific Agent Skills：把科研工作流交给 AI Agent 的技能库</title>
        <link>https://knightli.com/2026/05/17/scientific-agent-skills/</link>
        <pubDate>Sun, 17 May 2026 17:52:04 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/17/scientific-agent-skills/</guid>
        <description>&lt;p&gt;&lt;code&gt;K-Dense-AI/scientific-agent-skills&lt;/code&gt; 是一个面向科研和研究工作的 Agent Skills 集合。&lt;/p&gt;
&lt;p&gt;它的定位不是再做一个聊天机器人，而是把科研里经常要查文档、连数据库、写分析脚本、处理文件、生成图表和整理报告的流程，拆成一组可以被 AI Agent 发现和调用的技能。&lt;/p&gt;
&lt;p&gt;项目地址：&lt;a class=&#34;link&#34; href=&#34;https://github.com/K-Dense-AI/scientific-agent-skills&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/K-Dense-AI/scientific-agent-skills&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;截至 2026-05-17 写作时，GitHub API 显示这个仓库约有 23.4k stars、2.5k forks，许可证为 MIT，最近一次推送时间是 2026-05-11。README 里写的是 135 个 ready-to-use scientific and research skills，不过仓库 &lt;code&gt;scientific-skills&lt;/code&gt; 目录当前通过 GitHub API 能看到 137 个条目。这个差异可能来自统计口径、近期新增目录或 README 尚未同步更新。&lt;/p&gt;
&lt;h2 id=&#34;先说结论&#34;&gt;先说结论
&lt;/h2&gt;&lt;p&gt;Scientific Agent Skills 适合已经在用 Codex、Claude Code、Cursor、Gemini CLI 或其他支持 Agent Skills 标准工具的人。&lt;/p&gt;
&lt;p&gt;它的价值主要在三点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;把科研工具链的使用方式写成 &lt;code&gt;SKILL.md&lt;/code&gt;，让 agent 不必每次从零猜库怎么用。&lt;/li&gt;
&lt;li&gt;把常见科学数据库、Python 包、文档处理、科研写作和可视化流程整理到同一个技能集合里。&lt;/li&gt;
&lt;li&gt;让 AI Agent 更像一个能执行科研工作流的助手，而不只是回答概念问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但它也不是“装上就自动做科研”的魔法按钮。技能可以让 agent 更容易找到正确工具、生成更靠谱的代码和流程，但数据质量、实验设计、统计假设、临床或科研结论仍然需要人来判断。&lt;/p&gt;
&lt;h2 id=&#34;它包含什么&#34;&gt;它包含什么
&lt;/h2&gt;&lt;p&gt;README 把这个项目描述为一个覆盖科研、科学计算、工程、分析、金融和写作任务的技能集合。大类包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;生物信息学与基因组学&lt;/li&gt;
&lt;li&gt;化学信息学与药物发现&lt;/li&gt;
&lt;li&gt;蛋白质组学与质谱分析&lt;/li&gt;
&lt;li&gt;临床研究与精准医学&lt;/li&gt;
&lt;li&gt;医疗 AI 与临床机器学习&lt;/li&gt;
&lt;li&gt;医学影像与数字病理&lt;/li&gt;
&lt;li&gt;机器学习与 AI&lt;/li&gt;
&lt;li&gt;材料科学与化学&lt;/li&gt;
&lt;li&gt;物理与天文学&lt;/li&gt;
&lt;li&gt;工程仿真与优化&lt;/li&gt;
&lt;li&gt;数据分析与可视化&lt;/li&gt;
&lt;li&gt;地理空间科学与遥感&lt;/li&gt;
&lt;li&gt;实验室自动化&lt;/li&gt;
&lt;li&gt;科研写作、文献综述、同行评审和引用管理&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这类技能的重点不是限制 agent 只能使用某些库。README 也明确说，agent 仍然可以自己写 Python、调用任意可用 API 或包；这些技能的作用是提前提供整理过的说明、示例、最佳实践和集成路径。&lt;/p&gt;
&lt;p&gt;换句话说，它更像“科研工具说明书 + 工作流模板 + agent 调用约定”的集合。&lt;/p&gt;
&lt;h2 id=&#34;数据库和-python-包覆盖&#34;&gt;数据库和 Python 包覆盖
&lt;/h2&gt;&lt;p&gt;项目里最吸引科研用户的部分，是数据库和 Python 科学生态的覆盖面。&lt;/p&gt;
&lt;p&gt;README 提到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;通过 &lt;code&gt;database-lookup&lt;/code&gt; 统一访问 78 个公共数据库。&lt;/li&gt;
&lt;li&gt;覆盖 PubChem、ChEMBL、UniProt、COSMIC、ClinicalTrials.gov、FRED、USPTO 等数据库。&lt;/li&gt;
&lt;li&gt;额外包含 DepMap、Imaging Data Commons、PrimeKG、U.S. Treasury Fiscal Data、Hugging Science 等专门数据访问技能。&lt;/li&gt;
&lt;li&gt;提供 70+ 个优化过的 Python Package Skills。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;从目录看，技能名里能看到很多熟悉工具：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rdkit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scanpy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;biopython&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bioservices&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pydeseq2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scvelo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scvi-tools&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pymatgen&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;qiskit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pennylane&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;openmm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mdanalysis&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scikit-learn&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;statsmodels&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;matplotlib&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;seaborn&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;networkx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sympy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pytorch-lightning&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transformers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;timesfm-forecasting&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对普通开发者来说，这些库本身不稀奇。真正有用的是：agent 在处理具体任务时，可以读到与该库相关的使用约束、代码样例、常见流程和注意事项。这样比只靠模型参数里的旧记忆更稳。&lt;/p&gt;
&lt;h2 id=&#34;典型场景&#34;&gt;典型场景
&lt;/h2&gt;&lt;p&gt;Scientific Agent Skills 更适合多步骤科研任务，而不是单轮问答。&lt;/p&gt;
&lt;p&gt;比如药物发现方向，可以让 agent 查询 ChEMBL 里的 EGFR 抑制剂，用 RDKit 分析结构活性关系，再用 DiffDock 做虚拟筛选，最后搜索文献并生成报告。&lt;/p&gt;
&lt;p&gt;单细胞分析方向，可以把 10X 数据加载到 Scanpy，做质控、整合、细胞类型识别、差异表达和通路富集。&lt;/p&gt;
&lt;p&gt;多组学方向，可以把 RNA-seq、质谱、代谢物、蛋白互作、临床试验和统计建模串起来。&lt;/p&gt;
&lt;p&gt;这些任务如果完全靠手写 prompt，很容易变成“agent 知道大概方向，但每一步都要你提醒”。技能库的意义，就是把这类高频路径沉淀下来，让 agent 在执行时少走弯路。&lt;/p&gt;
&lt;h2 id=&#34;安装方式&#34;&gt;安装方式
&lt;/h2&gt;&lt;p&gt;README 推荐的标准安装方式是使用 Agent Skills 工具：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npx skills add K-Dense-AI/scientific-agent-skills
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果使用 GitHub CLI，并且版本为 &lt;code&gt;v2.90.0+&lt;/code&gt;，也可以通过 &lt;code&gt;gh skill&lt;/code&gt; 安装：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gh skill install K-Dense-AI/scientific-agent-skills
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;安装某个具体技能：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gh skill install K-Dense-AI/scientific-agent-skills scanpy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;指定目标 agent：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gh skill install K-Dense-AI/scientific-agent-skills --agent codex
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gh skill install K-Dense-AI/scientific-agent-skills --agent cursor
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gh skill install K-Dense-AI/scientific-agent-skills --agent claude-code
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gh skill install K-Dense-AI/scientific-agent-skills --agent gemini
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果要保证可复现，可以 pin 到 release tag 或 commit SHA：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gh skill install K-Dense-AI/scientific-agent-skills --pin v1.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gh skill install K-Dense-AI/scientific-agent-skills --pin abc123def
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这点对科研环境很重要。科研分析里最怕“上周能跑、这周结果变了但不知道为什么”。如果技能参与了分析流程，最好把技能版本、依赖版本和数据版本一起记录。&lt;/p&gt;
&lt;h2 id=&#34;运行环境要求&#34;&gt;运行环境要求
&lt;/h2&gt;&lt;p&gt;README 给出的基本要求包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Python 3.11+，推荐 3.12+&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uv&lt;/code&gt;，用于安装 Python 依赖&lt;/li&gt;
&lt;li&gt;支持 Agent Skills 标准的客户端&lt;/li&gt;
&lt;li&gt;macOS、Linux 或 Windows with WSL2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这里要注意 Windows 用户的实际体验。很多科学计算库在原生 Windows 下并不是不能用，但依赖链、编译工具、二进制包和路径问题更容易出意外。README 明确写 Windows with WSL2，也说明项目更偏向类 Unix 科研计算环境。&lt;/p&gt;
&lt;h2 id=&#34;和普通-prompt-集合有什么区别&#34;&gt;和普通 prompt 集合有什么区别
&lt;/h2&gt;&lt;p&gt;普通 prompt 集合通常只告诉模型“你应该怎么回答”。Scientific Agent Skills 更进一步：它把工具、库、数据库和流程写成 agent 可发现的技能。&lt;/p&gt;
&lt;p&gt;这有几个实际差异：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;技能可以包含结构化说明和示例代码。&lt;/li&gt;
&lt;li&gt;技能可以围绕某个库或数据库长期维护。&lt;/li&gt;
&lt;li&gt;agent 可以按任务选择相关技能，而不是一次性把所有规则塞进系统提示。&lt;/li&gt;
&lt;li&gt;团队可以只安装自己需要的技能，减少上下文噪音。&lt;/li&gt;
&lt;li&gt;技能可以跟随仓库版本管理、审计和更新。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对复杂科研任务来说，这种方式比“复制一大段万能提示词”更容易维护。模型会变，数据库会变，Python 包也会变。把这些变化沉淀在技能里，比散落在个人 prompt 文档里更可控。&lt;/p&gt;
&lt;h2 id=&#34;安全和可信边界&#34;&gt;安全和可信边界
&lt;/h2&gt;&lt;p&gt;这个项目的 README 把安全提醒写得很直接：Skills 可以执行代码，也会影响 coding agent 的行为。&lt;/p&gt;
&lt;p&gt;这不是小事。科研技能可能会：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;安装 Python 依赖&lt;/li&gt;
&lt;li&gt;访问网络数据库&lt;/li&gt;
&lt;li&gt;读写本地文件&lt;/li&gt;
&lt;li&gt;运行分析脚本&lt;/li&gt;
&lt;li&gt;处理敏感实验数据或临床数据&lt;/li&gt;
&lt;li&gt;生成后续会被人引用的报告&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此不要无脑安装全部技能。更稳的做法是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;只安装当前任务需要的技能。&lt;/li&gt;
&lt;li&gt;安装前阅读对应 &lt;code&gt;SKILL.md&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;检查技能会调用哪些包、API、文件和外部服务。&lt;/li&gt;
&lt;li&gt;对社区贡献的技能额外谨慎。&lt;/li&gt;
&lt;li&gt;在隔离环境里运行涉及数据处理和代码执行的任务。&lt;/li&gt;
&lt;li&gt;对科研结论、临床建议和统计结果保留人工复核。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;README 还提到项目会使用 Cisco AI Defense Skill Scanner 做扫描，并建议用户也可以本地扫描第三方技能。扫描不能替代人工审查，但至少说明维护者意识到技能供应链风险。&lt;/p&gt;
&lt;h2 id=&#34;适合谁&#34;&gt;适合谁
&lt;/h2&gt;&lt;p&gt;这个项目更适合这些人：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;已经在日常使用 AI coding agent。&lt;/li&gt;
&lt;li&gt;经常处理科研数据、论文、图表和报告。&lt;/li&gt;
&lt;li&gt;需要在 Python 科学生态里频繁切换工具。&lt;/li&gt;
&lt;li&gt;想让 agent 执行多步骤分析，而不是只回答概念。&lt;/li&gt;
&lt;li&gt;团队希望把科研流程沉淀成可复用技能。&lt;/li&gt;
&lt;li&gt;想研究 Agent Skills 标准如何落地到专业领域。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;暂时不太适合这些场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;只是想让 AI 帮忙解释一篇论文。&lt;/li&gt;
&lt;li&gt;没有本地 Python 环境或不愿意处理依赖。&lt;/li&gt;
&lt;li&gt;对数据隐私、网络访问和代码执行边界还没有控制方案。&lt;/li&gt;
&lt;li&gt;需要严格合规的临床或生产决策系统，但没有人工审查和验证流程。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果只是偶尔做一次分析，直接让 agent 写脚本可能更轻。如果你经常重复类似科研流程，技能库的价值会更明显。&lt;/p&gt;
&lt;h2 id=&#34;使用建议&#34;&gt;使用建议
&lt;/h2&gt;&lt;p&gt;不要一开始就安装整个仓库，然后把所有任务都交给 agent。&lt;/p&gt;
&lt;p&gt;更实际的路径是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先选一个低风险任务，比如文献整理、图表生成或公开数据探索。&lt;/li&gt;
&lt;li&gt;只安装相关技能，比如 &lt;code&gt;literature-review&lt;/code&gt;、&lt;code&gt;scientific-writing&lt;/code&gt;、&lt;code&gt;scanpy&lt;/code&gt; 或 &lt;code&gt;rdkit&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;让 agent 先说明计划，再执行代码。&lt;/li&gt;
&lt;li&gt;保留输入数据、脚本、环境和技能版本。&lt;/li&gt;
&lt;li&gt;对输出结果做人工复查。&lt;/li&gt;
&lt;li&gt;如果流程稳定，再把它写入团队自己的 SOP 或技能。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;科研 agent 的关键不是“自动化一切”，而是把重复、繁琐、容易查错文档的部分交给工具，把判断、假设和结论留给人。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;Scientific Agent Skills 的意义，在于把 Agent Skills 从通用编程场景推进到科研场景。&lt;/p&gt;
&lt;p&gt;科研工作天然是多工具、多数据库、多文件、多步骤的流程。单靠聊天式 prompt，很难稳定覆盖这些细节。这个项目把常见科学库、数据源和研究流程整理成技能，让 AI Agent 更容易进入真实科研工作流。&lt;/p&gt;
&lt;p&gt;但它越强，也越需要边界感。技能会影响 agent 行为，也可能运行代码、联网和处理文件。安装前要看清楚技能内容，运行时要隔离环境，科研结论更不能跳过人工验证。&lt;/p&gt;
&lt;p&gt;如果你已经在用 Codex、Claude Code、Cursor 或 Gemini CLI 做科研和数据分析，Scientific Agent Skills 值得认真看一眼。哪怕不直接全量安装，它的技能拆分方式也很适合作为团队整理科研 AI 工作流的参考。&lt;/p&gt;
&lt;p&gt;参考链接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/K-Dense-AI/scientific-agent-skills&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;K-Dense-AI/scientific-agent-skills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/K-Dense-AI/scientific-agent-skills/blob/main/README.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;README 原文&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://agentskills.io/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Agent Skills 标准&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/K-Dense-AI/k-dense-byok&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;K-Dense BYOK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.blog/changelog/2026-04-16-manage-agent-skills-with-github-cli/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub CLI gh skill changelog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Codex 支持 ChatGPT 移动端远程访问，Enterprise 工作区可用 Access Tokens</title>
        <link>https://knightli.com/2026/05/17/codex-mobile-remote-access-enterprise-access-tokens/</link>
        <pubDate>Sun, 17 May 2026 09:12:07 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/17/codex-mobile-remote-access-enterprise-access-tokens/</guid>
        <description>&lt;p&gt;OpenAI 在 2026 年 5 月 14 日更新了 ChatGPT Enterprise &amp;amp; Edu Release Notes，重点只有两件事：Codex 支持通过 ChatGPT 移动端远程访问，Enterprise 工作区可以使用 Codex access tokens 做受控自动化。&lt;/p&gt;
&lt;p&gt;这不是一次模型能力发布，而是 Codex 产品形态的变化。Codex 正在从“本地或网页里的编程助手”，变成可以长时间运行、可以远程接管、可以接入企业自动化流程的 coding agent。&lt;/p&gt;
&lt;h2 id=&#34;这次更新是什么&#34;&gt;这次更新是什么
&lt;/h2&gt;&lt;p&gt;根据 OpenAI Help Center 的说明，Codex 现在支持从 ChatGPT mobile app 远程访问。用户可以在手机上连接正在运行的 Codex 环境，持续跟进长时间任务，并在需要时介入。&lt;/p&gt;
&lt;p&gt;同时，ChatGPT Enterprise 工作区新增 Codex access tokens。它们面向可信的非交互式本地工作流，让自动化流程可以使用 ChatGPT workspace identity 和企业控制，而不需要每次通过浏览器登录。&lt;/p&gt;
&lt;p&gt;可以把这次更新理解成两个入口：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;移动端远程访问：解决“Codex 跑长任务时，人不在电脑前怎么办”。&lt;/li&gt;
&lt;li&gt;Access Tokens：解决“企业自动化脚本如何以受控身份调用 Codex 工作流”。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;移动端远程访问解决什么问题&#34;&gt;移动端远程访问解决什么问题
&lt;/h2&gt;&lt;p&gt;Codex 的典型任务并不总是几秒钟完成。真实开发里，它可能要阅读代码库、修改多个文件、运行测试、等待命令输出、根据错误继续修复，甚至需要用户中途批准某些操作。&lt;/p&gt;
&lt;p&gt;过去这类任务往往要求用户守在本地 Mac、桌面端、CLI 或 IDE 旁边。现在，ChatGPT 移动端可以变成一个远程控制台，让用户离开电脑后仍能跟进 Codex。&lt;/p&gt;
&lt;p&gt;OpenAI 提到，移动端可以展示底层环境的实时状态，包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;项目上下文。&lt;/li&gt;
&lt;li&gt;approvals。&lt;/li&gt;
&lt;li&gt;screenshots。&lt;/li&gt;
&lt;li&gt;terminal output。&lt;/li&gt;
&lt;li&gt;diffs。&lt;/li&gt;
&lt;li&gt;test results。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;用户也可以在手机上回答 Codex 的问题、重定向执行、批准操作、查看输出，并在不同 connected hosts 之间切换。底层任务仍然运行在 Mac host 或连接的远程环境中，手机端负责查看和控制。&lt;/p&gt;
&lt;h2 id=&#34;这对开发者有什么价值&#34;&gt;这对开发者有什么价值
&lt;/h2&gt;&lt;p&gt;这项能力最适合长时间、需要中途确认的开发任务。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Codex 正在跑一组耗时测试，你出门后仍想看结果。&lt;/li&gt;
&lt;li&gt;Codex 修改了多个文件，需要你在手机上看 diff 后批准下一步。&lt;/li&gt;
&lt;li&gt;Codex 执行到某个危险操作前等待确认，你可以远程处理。&lt;/li&gt;
&lt;li&gt;本地 Mac 上有多个 connected hosts，需要在手机上切换查看状态。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它的价值不是让你在手机上写代码，而是让你不用一直守着电脑。Codex 继续在原环境里工作，你只在关键节点介入。&lt;/p&gt;
&lt;p&gt;这也说明 Codex 的使用方式正在接近“后台 Agent”：任务可以持续运行，用户不必全程在线，但仍要保留审批和控制权。&lt;/p&gt;
&lt;h2 id=&#34;access-tokens-解决什么问题&#34;&gt;Access Tokens 解决什么问题
&lt;/h2&gt;&lt;p&gt;Codex access tokens 面向 ChatGPT Enterprise 工作区。它们的重点不是普通个人用户登录，而是企业内部可信自动化。&lt;/p&gt;
&lt;p&gt;企业里经常有一些本地或内部流程需要非交互式运行，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;定时执行代码检查。&lt;/li&gt;
&lt;li&gt;在受控机器上触发 Codex 工作流。&lt;/li&gt;
&lt;li&gt;将 Codex 接入内部开发工具链。&lt;/li&gt;
&lt;li&gt;在不打开浏览器的情况下使用工作区身份。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Access tokens 让这些流程可以带着 ChatGPT workspace identity 运行，同时继续受企业策略约束。相比临时人工登录，它更适合自动化；相比随便共享个人凭据，它也更容易纳入治理。&lt;/p&gt;
&lt;h2 id=&#34;它不是普通-api-key&#34;&gt;它不是普通 API key
&lt;/h2&gt;&lt;p&gt;这点很重要。Codex access tokens 不应该被理解成一个简单的“万能 API key”。&lt;/p&gt;
&lt;p&gt;OpenAI 的说明里提到，access tokens 可用于 ChatGPT Enterprise 工作区，管理员可以管理工作区级可用性，拥有允许角色的成员可以创建自己的 tokens。治理界面在可用情况下也会反映 access token 活动。&lt;/p&gt;
&lt;p&gt;也就是说，access tokens 被放在企业权限、角色和审计框架里：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;管理员可以决定工作区是否开放。&lt;/li&gt;
&lt;li&gt;不是所有成员都天然可以创建。&lt;/li&gt;
&lt;li&gt;token 活动可以进入治理视图。&lt;/li&gt;
&lt;li&gt;它继承 ChatGPT workspace identity 和企业控制。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这和个人随手生成一个长期密钥不是一回事。&lt;/p&gt;
&lt;h2 id=&#34;安全默认值remote-control-默认关闭&#34;&gt;安全默认值：Remote Control 默认关闭
&lt;/h2&gt;&lt;p&gt;Codex mobile remote access 涉及代码环境、终端输出、diff、测试结果和操作审批。如果默认开放，会带来明显企业安全风险。&lt;/p&gt;
&lt;p&gt;因此 OpenAI 的默认策略是：remote control 默认关闭，管理员或 owner 需要在 Workspace settings 中启用。&lt;/p&gt;
&lt;p&gt;启用移动端远程访问时，还可能涉及：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;workspace-enabled Remote Control access。&lt;/li&gt;
&lt;li&gt;SSO。&lt;/li&gt;
&lt;li&gt;多因素认证。&lt;/li&gt;
&lt;li&gt;passkey。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这说明它是一个需要企业 IT 和安全团队参与配置的能力，而不是“更新 App 后所有人自动可用”。&lt;/p&gt;
&lt;h2 id=&#34;使用前需要更新什么&#34;&gt;使用前需要更新什么
&lt;/h2&gt;&lt;p&gt;OpenAI 提到，要使用移动端远程访问，需要更新两端：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ChatGPT mobile app。&lt;/li&gt;
&lt;li&gt;macOS 上的 Codex app。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果工作区启用了相关要求，移动端设置过程还可能触发 SSO、多因素认证或 passkey 流程。&lt;/p&gt;
&lt;p&gt;实际落地时，企业管理员还需要先确认 Workspace settings 里的 remote control 设置，以及哪些成员或角色可以使用相关能力。&lt;/p&gt;
&lt;h2 id=&#34;对企业-codex-使用方式的影响&#34;&gt;对企业 Codex 使用方式的影响
&lt;/h2&gt;&lt;p&gt;这次更新把 Codex 往两个方向推进。&lt;/p&gt;
&lt;p&gt;第一，Codex 更适合长任务。以前长任务最大的问题是用户要一直盯着，现在手机可以查看状态和批准操作，Codex 可以更自然地跑在后台。&lt;/p&gt;
&lt;p&gt;第二，Codex 更适合企业自动化。Access tokens 让非交互式工作流有了更正式的身份方式，后续更容易接入内部 CI、代码审查、脚本和开发平台。&lt;/p&gt;
&lt;p&gt;这两个方向结合起来，意味着 Codex 不再只是“开发者手边的 AI 助手”，而是在变成企业开发流程里的一个可管理 agent。&lt;/p&gt;
&lt;h2 id=&#34;仍然需要注意的边界&#34;&gt;仍然需要注意的边界
&lt;/h2&gt;&lt;p&gt;这次更新很有用，但并不意味着 Codex 可以完全无人看管。&lt;/p&gt;
&lt;p&gt;企业使用时仍然要注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;哪些项目允许远程控制。&lt;/li&gt;
&lt;li&gt;哪些命令需要审批。&lt;/li&gt;
&lt;li&gt;token 如何创建、轮换和撤销。&lt;/li&gt;
&lt;li&gt;mobile remote access 是否符合公司设备管理策略。&lt;/li&gt;
&lt;li&gt;终端输出、截图和 diff 是否可能包含敏感信息。&lt;/li&gt;
&lt;li&gt;审计日志和治理界面是否能满足内部合规要求。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;尤其是 access tokens，一旦进入自动化流程，就要像其他企业凭据一样管理：最小权限、定期轮换、避免硬编码、及时撤销不用的 token。&lt;/p&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结
&lt;/h2&gt;&lt;p&gt;OpenAI 这次 Codex 更新的重点很集中：ChatGPT 移动端可以远程访问 Codex 长任务，Enterprise 工作区可以用 Codex access tokens 支持受控自动化。&lt;/p&gt;
&lt;p&gt;前者让开发者不必一直守在电脑前，后者让企业可以把 Codex 更正式地接入内部工作流。两者合在一起，说明 Codex 正在从交互式编程助手，进一步走向可远程管理、可审计、可自动化接入的企业 coding agent。&lt;/p&gt;
&lt;p&gt;参考链接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/10128477-chatgpt-enterprise-edu-release-notes&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenAI Help Center：ChatGPT Enterprise &amp;amp; Edu - Release Notes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Codex 额度为什么突然重置？Usage Limits 历史与消息来源整理</title>
        <link>https://knightli.com/2026/05/17/codex-usage-limit-reset-history/</link>
        <pubDate>Sun, 17 May 2026 08:36:15 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/17/codex-usage-limit-reset-history/</guid>
        <description>&lt;p&gt;Codex 用户偶尔会遇到一种情况：明明还没到自己的常规 reset 时间，usage limits 却突然恢复了。这种“无预兆重置”不是第一次出现，也不一定代表额度规则永久变宽。它可能来自故障补偿、产品活动、增长里程碑，也可能只是某个窗口或部分账号状态被后台重置。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://knightli.com/2026/05/17/codex-usage-limit-reset-history/tibo-codex-gpt55-reset.png&#34;
	width=&#34;1146&#34;
	height=&#34;712&#34;
	srcset=&#34;https://knightli.com/2026/05/17/codex-usage-limit-reset-history/tibo-codex-gpt55-reset_hu_8e2e55bed895f615.png 480w, https://knightli.com/2026/05/17/codex-usage-limit-reset-history/tibo-codex-gpt55-reset_hu_1736ae030ba80b22.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Tibo 关于 Codex usage limits 重置的截图&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;160&#34;
		data-flex-basis=&#34;386px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;这张截图来自 OpenAI Codex 团队负责人 Tibo Sottiaux（@thsottiaux）在 X 上发布的公告。对额度用户来说，最关键的一句不是模型细节，而是：他表示会在当晚 reset usage limits。截图里的上下文说明，这次重置是一次补偿性操作，而不是普通周期刷新。&lt;/p&gt;
&lt;h2 id=&#34;先说结论&#34;&gt;先说结论
&lt;/h2&gt;&lt;p&gt;Codex 额度突然重置，大致可以分成几类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;故障补偿&lt;/strong&gt;：模型或 Codex 服务异常导致用户浪费额度，官方通过重置弥补。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;发布或推广活动&lt;/strong&gt;：新模型、新客户端、新功能上线时，临时提高或重置额度。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;增长里程碑&lt;/strong&gt;：用户规模达到某个节点后，官方用重置或提额鼓励继续使用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;后台策略调整&lt;/strong&gt;：部分额度窗口、部分账号状态被重置，但 UI 不一定解释清楚。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;普通用户最容易误解的是：看到“重置”就以为所有窗口都恢复了。实际上，Codex 可能同时有短窗口、weekly limit、不同模型和不同套餐限制。一次特殊重置可能只影响其中一部分。&lt;/p&gt;
&lt;h2 id=&#34;这次截图说明了什么&#34;&gt;这次截图说明了什么
&lt;/h2&gt;&lt;p&gt;截图显示，Tibo 在 2026 年 5 月 15 日发布更新，表示团队会继续监控，并在当晚重置 usage limits。它引用了前一条“正在调查部分用户反馈”的消息，因此这次重置更像一次服务波动后的补偿。&lt;/p&gt;
&lt;p&gt;对用户来说，可以提炼出三点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;这不是用户自己的常规周期到了，而是官方主动重置。&lt;/li&gt;
&lt;li&gt;这次重置有明确事件背景，不是永久提额公告。&lt;/li&gt;
&lt;li&gt;“usage limits” 的具体覆盖范围仍要看实际账号显示，截图本身没有解释 5 小时窗口、weekly limit 是否全部包含。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所以，如果你看到额度恢复，正确做法不是马上推断“以后都变宽了”，而是先把它当成一次特殊 reset event。&lt;/p&gt;
&lt;h2 id=&#34;为什么-codex-会无预兆重置&#34;&gt;为什么 Codex 会无预兆重置
&lt;/h2&gt;&lt;p&gt;Codex 的额度体系不是一个简单的“每天几点刷新”。用户界面通常只显示剩余额度或百分比，但后台可能同时跟踪：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;短时间窗口，例如几小时内的使用量。&lt;/li&gt;
&lt;li&gt;周额度或更长周期额度。&lt;/li&gt;
&lt;li&gt;不同模型的消耗权重。&lt;/li&gt;
&lt;li&gt;本地 Codex、Cloud Task、IDE/CLI 等不同入口。&lt;/li&gt;
&lt;li&gt;Plus、Pro、Business、Team 等不同套餐。&lt;/li&gt;
&lt;li&gt;账号是否满足某次特殊重置的后台条件。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当 OpenAI 做一次特殊重置时，用户未必能看到“这是普通周期恢复，还是特殊补偿”。如果只重置短窗口，用户可能误以为 weekly 也应该恢复；如果 weekly 没变，就会怀疑重置失败。&lt;/p&gt;
&lt;p&gt;OpenAI 的 Codex GitHub issue 里也有人专门反馈过这个透明度问题：公开说 reset Codex rate limits，但产品 UI 没有说明到底重置了哪些窗口、是否包含 weekly limit、是否所有付费计划都一致生效。这也是“无预兆重置”让人困惑的核心原因。&lt;/p&gt;
&lt;h2 id=&#34;历史上的几类重置&#34;&gt;历史上的几类重置
&lt;/h2&gt;&lt;h3 id=&#34;1-2026-年-2-月发布期与临时加量&#34;&gt;1. 2026 年 2 月：发布期与临时加量
&lt;/h3&gt;&lt;p&gt;Codex 桌面应用和 &lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 推广期间，社区用户讨论过 usage limit reset 和临时 2x rate limits。Reddit 上有用户提到 Codex app 刚发布时提供过限时 2x rate limits，并伴随 usage limit reset。&lt;/p&gt;
&lt;p&gt;这类重置更像发布期运营动作：让更多用户试用新客户端、新模型或新工作流。&lt;/p&gt;
&lt;h3 id=&#34;2-2026-年-3-月随机重置与异常消耗讨论&#34;&gt;2. 2026 年 3 月：随机重置与异常消耗讨论
&lt;/h3&gt;&lt;p&gt;3 月前后，社区里多次出现“random usage reset”“weekly limit reset daily”之类帖子。有用户反馈自己的 weekly limit 被提前恢复，也有人认为这和 Codex 新模型、新安全拦截、异常消耗或 bug 修复有关。&lt;/p&gt;
&lt;p&gt;这些讨论不等同于官方公告，但它们说明一件事：用户侧已经多次观察到额度并非只按固定周期恢复。某些情况下，后台会因为问题修复或补偿而触发额外 reset。&lt;/p&gt;
&lt;h3 id=&#34;3-2026-年-4-月增长里程碑与付费计划重置&#34;&gt;3. 2026 年 4 月：增长里程碑与付费计划重置
&lt;/h3&gt;&lt;p&gt;4 月下旬，有公开报道提到 Codex 达到 300 万周活用户后，OpenAI 重置了 rate limits，并计划在后续用户增长里程碑继续给用户更多额度空间。&lt;/p&gt;
&lt;p&gt;GitHub issue 中也引用过 Tibo 4 月 28 日的 X 公告：他提到曾为“good week”重置付费计划的 Codex rate limits，让用户可以更多使用 &lt;code&gt;GPT-5.5&lt;/code&gt;。不过同一个 issue 也指出，实际产品 UI 没有清楚说明到底哪些额度窗口被重置，weekly limit 是否全部包含。&lt;/p&gt;
&lt;p&gt;这说明增长或活动型重置，往往也会带来解释成本：用户听到“all paid plans”，但账号里看到的结果未必完全一致。&lt;/p&gt;
&lt;h3 id=&#34;4-2026-年-5-月故障补偿型重置&#34;&gt;4. 2026 年 5 月：故障补偿型重置
&lt;/h3&gt;&lt;p&gt;这次截图属于更典型的故障补偿型重置。Tibo 明确说团队找到了问题并会在当晚 reset usage limits。OpenAI Status 也记录过 2026 年 5 月 13 日 Codex 相关高错误率和延迟退化事件。&lt;/p&gt;
&lt;p&gt;对普通用户而言，这次重点不是某个模型是否变差，而是：当服务端问题让用户额度被异常消耗时，OpenAI 可能会通过特殊重置来补偿。&lt;/p&gt;
&lt;h2 id=&#34;用户该怎么判断一次重置来自哪里&#34;&gt;用户该怎么判断一次重置来自哪里
&lt;/h2&gt;&lt;p&gt;遇到 Codex 额度突然恢复，可以按这个顺序判断：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先看自己的常规 reset 时间，排除普通周期恢复。&lt;/li&gt;
&lt;li&gt;看 OpenAI Status 是否有 Codex、模型错误率、延迟或降级记录。&lt;/li&gt;
&lt;li&gt;看 Tibo、OpenAI 官方账号、Codex GitHub issue 是否有说明。&lt;/li&gt;
&lt;li&gt;看社区反馈是否集中出现“突然 reset”“额度燃烧异常”“weekly 没恢复”等讨论。&lt;/li&gt;
&lt;li&gt;区分短窗口和 weekly limit，不要默认所有窗口都会一起恢复。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果是官方事故补偿，通常会伴随状态页记录、负责人公告或大量用户集中反馈。如果只是后台部分窗口刷新，可能不会有明确公告。&lt;/p&gt;
&lt;h2 id=&#34;消息来源怎么分辨可靠性&#34;&gt;消息来源怎么分辨可靠性
&lt;/h2&gt;&lt;p&gt;这类消息最好分层看：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;官方状态页&lt;/strong&gt;：最适合确认是否有服务故障、错误率、延迟、恢复时间。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tibo / OpenAI 官方账号&lt;/strong&gt;：适合确认是否有特殊 reset、补偿或活动口径。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenAI Codex GitHub issue&lt;/strong&gt;：适合看用户对 UI、额度窗口、实际行为的反馈。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;社区 Reddit / X 讨论&lt;/strong&gt;：适合观察用户是否普遍遇到类似现象，但不能直接当成官方结论。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;第三方新闻或博客&lt;/strong&gt;：适合补充时间线，但仍要回到官方和原始链接核对。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;写文章或做判断时，最好把这些来源分开写。比如“OpenAI Status 记录了服务问题”是官方状态；“Reddit 用户反馈随机重置”是社区观察；“GitHub issue 反映 UI 不透明”是用户提交的问题描述。&lt;/p&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结
&lt;/h2&gt;&lt;p&gt;Codex 额度突然重置，通常不是一个单纯的“系统送额度”。它可能来自故障补偿、发布期推广、增长活动或后台策略调整。真正容易造成误解的地方在于：Codex 同时存在多个额度窗口，而特殊 reset 不一定覆盖所有窗口，UI 也不一定清楚展示 reset scope。&lt;/p&gt;
&lt;p&gt;所以，遇到无预兆重置时，最稳的判断方式是：先看客户端实际额度，再查 OpenAI Status、Tibo 公告、Codex GitHub issue 和社区反馈。不要只凭一次 reset 推断长期额度规则，也不要默认 weekly limit、短窗口和所有套餐都会同步恢复。&lt;/p&gt;
&lt;p&gt;参考链接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://status.openai.com/incidents/01KRG6MF021JQ997JCR7R8Y9A0&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenAI Status：Codex 5.5 engines are experiencing high error rate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.reddit.com/r/LovingCodex/comments/1teo5ki/tibo_we_foundfixed_two_issues_that_could_explain/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Reddit 转发的 Tibo 公告截图与 X 链接&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/openai/codex/issues/20395&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub：Clarify Codex rate-limit reset behavior and make reset scope visible in Usage UI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.createwith.com/tool/chatgpt/updates/chatgpt-codex-hits-3-million-weekly-users-openai-resets-rate-limits&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Create With：ChatGPT Codex Hits 3 Million Weekly Users, OpenAI Resets Rate Limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.reddit.com/r/codex/comments/1rjcwli/usage_limit_reset/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Reddit：Usage limit reset?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.reddit.com/r/codex/comments/1qu2gjx/when_the_unnexpected_usage_limit_reset_hits_ty/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Reddit：when the unexpected usage limit reset hits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Codex 手机远程访问来了：用 ChatGPT App 跟进 Mac 上的编程任务</title>
        <link>https://knightli.com/2026/05/16/codex-mobile-remote-access-chatgpt-app/</link>
        <pubDate>Sat, 16 May 2026 17:42:40 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/16/codex-mobile-remote-access-chatgpt-app/</guid>
        <description>&lt;p&gt;OpenAI 在 2026 年 5 月中旬把 &lt;code&gt;Codex remote access&lt;/code&gt; 带进了 ChatGPT 手机 App。这个功能的重点不是“在手机上写代码”，而是让你用手机远程跟进 Mac 上正在运行的 Codex。&lt;/p&gt;
&lt;p&gt;它更像一个移动审批和监控入口：Codex 继续在电脑上读项目、跑命令、改文件、看测试结果；手机端负责查看进度、回答问题、补充指令和批准操作。&lt;/p&gt;
&lt;p&gt;对经常让 Codex 跑长任务的人来说，这个变化很实用。你不必一直坐在电脑前等它卡在哪里，出门或离开工位后，也能从 ChatGPT App 里接上现场。&lt;/p&gt;
&lt;h2 id=&#34;它能做什么&#34;&gt;它能做什么
&lt;/h2&gt;&lt;p&gt;根据 OpenAI Codex remote connections 文档，手机端远程访问可以做这些事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在 Mac 主机上的项目里开启新线程，或继续已有线程；&lt;/li&gt;
&lt;li&gt;发送后续指令，回答 Codex 提出的问题，调整任务方向；&lt;/li&gt;
&lt;li&gt;批准命令和其他操作；&lt;/li&gt;
&lt;li&gt;查看输出、diff、测试结果、终端输出和截图；&lt;/li&gt;
&lt;li&gt;在 Codex 完成任务或需要你注意时收到通知；&lt;/li&gt;
&lt;li&gt;在多个已连接主机和线程之间切换。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也就是说，手机端不是一个简化版聊天窗口，而是接入了 Codex 当前工作现场。你看到的不只是模型回复，还有它在主机上产生的工程上下文。&lt;/p&gt;
&lt;h2 id=&#34;使用前需要什么&#34;&gt;使用前需要什么
&lt;/h2&gt;&lt;p&gt;当前手机远程访问有几个前提。&lt;/p&gt;
&lt;p&gt;第一，你需要有可用的 Codex 权限，并且手机和 Mac 使用同一个 ChatGPT 账号与 workspace。&lt;/p&gt;
&lt;p&gt;第二，手机上要安装最新版 ChatGPT App，iOS 或 Android 都可以。如果 App 里看不到 Codex，先更新 ChatGPT。&lt;/p&gt;
&lt;p&gt;第三，主机目前要求是 Mac，并且需要保持在线、唤醒、正在运行 Codex App。OpenAI 文档明确写到，移动端设置和设备控制当前需要主机上运行 &lt;code&gt;Codex App for macOS&lt;/code&gt;，不能从 Codex CLI 或 IDE Extension 里完成设置。&lt;/p&gt;
&lt;p&gt;第四，如果账号或 workspace 要求 MFA、SSO 或 passkey，需要先完成对应认证。团队 workspace 还可能需要管理员开启 Remote Control access。&lt;/p&gt;
&lt;p&gt;这些限制说明它目前更像是 Codex App for macOS 的移动控制能力，而不是通用远程桌面，也不是所有 Codex 入口都能用。&lt;/p&gt;
&lt;h2 id=&#34;codex-手机远程访问的限制&#34;&gt;Codex 手机远程访问的限制
&lt;/h2&gt;&lt;p&gt;这个功能虽然很方便，但限制也要提前看清楚。&lt;/p&gt;
&lt;p&gt;第一，当前需要 &lt;code&gt;macOS host&lt;/code&gt;。手机端连接的是 Mac 上运行的 Codex App，不是直接连接 Codex CLI、IDE Extension，也不是任意 Linux / Windows 开发机。&lt;/p&gt;
&lt;p&gt;第二，主机必须在线。Mac 需要保持唤醒、联网，并持续运行 Codex App。如果电脑睡眠、断网或 Codex 关闭，手机端远程会话就可能断开。&lt;/p&gt;
&lt;p&gt;第三，连接依赖扫码流程。你需要先在 Mac 端打开 &lt;code&gt;Set up Codex mobile&lt;/code&gt;，再用手机扫描二维码进入 ChatGPT 完成绑定。它不是输入一个地址就能直接连，也不是纯账号登录后自动发现所有设备。&lt;/p&gt;
&lt;p&gt;第四，远程操作仍然要经过审批流程。手机端可以批准命令和其他操作，但这也意味着你需要看清 Codex 请求做什么，再决定是否继续。尤其是涉及终端命令、文件修改、测试运行和外部访问时，不应该把手机审批当成无脑点确认。&lt;/p&gt;
&lt;p&gt;所以它适合“人离开电脑后继续跟进任务”，不适合替代完整开发环境，也不适合把主机长期无人值守地开放给远程操作。&lt;/p&gt;
&lt;h2 id=&#34;怎么连接&#34;&gt;怎么连接
&lt;/h2&gt;&lt;p&gt;设置流程从 Mac 上的 Codex App 开始。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在 Mac 上打开 Codex。&lt;/li&gt;
&lt;li&gt;在侧边栏选择 &lt;code&gt;Set up Codex mobile&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;Codex 会为这台主机开启远程访问，并显示一个二维码。&lt;/li&gt;
&lt;li&gt;用手机扫描二维码，进入 ChatGPT 里的 Codex mobile setup 流程。&lt;/li&gt;
&lt;li&gt;确认同一个 ChatGPT 账号和 workspace。&lt;/li&gt;
&lt;li&gt;完成必要的 MFA、SSO 或 passkey 验证。&lt;/li&gt;
&lt;li&gt;设置成功后，这台 Mac 会出现在手机端 Codex 里。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;连接完成后，可以在 Mac 端 Codex 的 &lt;code&gt;Settings &amp;gt; Connections&lt;/code&gt; 管理已连接设备。这里也可以设置是否让电脑保持唤醒、是否启用 Computer Use、是否安装 Chrome extension。&lt;/p&gt;
&lt;h2 id=&#34;手机端适合干什么&#34;&gt;手机端适合干什么
&lt;/h2&gt;&lt;p&gt;手机端最适合三类操作。&lt;/p&gt;
&lt;p&gt;第一类是审批。Codex 需要运行命令、访问文件、继续某个动作时，你可以在手机上看清请求，再决定是否批准。&lt;/p&gt;
&lt;p&gt;第二类是纠偏。比如 Codex 走偏了、误解了需求、测试失败后需要你选方向，你可以直接补一句说明，让它继续处理。&lt;/p&gt;
&lt;p&gt;第三类是查看结果。你可以看 diff、测试输出、终端日志和截图，不必回到电脑前才知道任务跑成什么样。&lt;/p&gt;
&lt;p&gt;这和“手机写代码”不是一回事。真正有价值的是把手机变成工程任务的随身控制台，让 Codex 在主机上干重活，人只在关键节点介入。&lt;/p&gt;
&lt;h2 id=&#34;常见问题&#34;&gt;常见问题
&lt;/h2&gt;&lt;p&gt;如果手机上看不到主机，先确认 Mac 上 Codex App 仍在运行，并且开启了 &lt;code&gt;Allow other devices to connect&lt;/code&gt;。手机和主机也必须使用同一个 ChatGPT 账号与 workspace。&lt;/p&gt;
&lt;p&gt;如果审批请求没有出现，可以打开 ChatGPT 手机 App，进入 Codex，再重新扫码或从主机重新开始设置。团队账号还要确认管理员是否已经允许 Remote Control access。&lt;/p&gt;
&lt;p&gt;如果远程会话断开，通常要检查三件事：Mac 是否睡眠、网络是否断开、Codex App 是否关闭。远程访问依赖主机保持唤醒和联网。&lt;/p&gt;
&lt;p&gt;如果认证卡住，就先完成账号或 workspace 的 MFA、SSO、passkey 流程。企业环境里，权限问题往往要管理员介入。&lt;/p&gt;
&lt;h2 id=&#34;适合哪些场景&#34;&gt;适合哪些场景
&lt;/h2&gt;&lt;p&gt;这个功能适合这些人：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;经常让 Codex 跑较长的代码修改任务；&lt;/li&gt;
&lt;li&gt;需要在通勤、会议间隙、离开工位时继续跟进任务；&lt;/li&gt;
&lt;li&gt;希望及时审批命令，而不是让 Codex 停在等待状态；&lt;/li&gt;
&lt;li&gt;同时管理多个项目或多个 Codex 线程；&lt;/li&gt;
&lt;li&gt;使用 Mac 作为主力开发机，并已经习惯 Codex App。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不太适合这些场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主要使用 Windows 或 Linux 主机；&lt;/li&gt;
&lt;li&gt;只用 Codex CLI 或 IDE Extension；&lt;/li&gt;
&lt;li&gt;希望手机端独立完成完整开发环境；&lt;/li&gt;
&lt;li&gt;网络不稳定，或 Mac 经常休眠；&lt;/li&gt;
&lt;li&gt;团队 workspace 没有开启远程控制权限。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;我的判断&#34;&gt;我的判断
&lt;/h2&gt;&lt;p&gt;Codex 手机远程访问的意义，不是把开发工作搬到手机屏幕上，而是把“等待 Codex 跑完”的时间变得更可控。&lt;/p&gt;
&lt;p&gt;以前 Codex 长任务经常卡在审批、追问、测试失败或方向确认上。现在这些节点可以通过 ChatGPT 手机 App 处理，Mac 继续做真正的工程执行，手机负责轻量决策。&lt;/p&gt;
&lt;p&gt;这会让 Codex 更像后台工程代理：它可以在电脑上持续工作，人不用一直盯着终端，只需要在需要判断的时候回来。限制也很清楚，目前它强依赖 macOS 上的 Codex App、同一账号 workspace、主机在线和组织权限。&lt;/p&gt;
&lt;p&gt;如果你已经在 Mac 上重度使用 Codex，这个功能值得开启。如果你还只是偶尔问几句代码问题，它的价值可能没有那么明显。&lt;/p&gt;
&lt;h2 id=&#34;参考资料&#34;&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/6825453-chatgpt-release-notes&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenAI Help Center：ChatGPT Release Notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://developers.openai.com/codex/remote-connections&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenAI Developers：Codex Remote Connections&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Superpowers：把 Coding Agent 拉回工程流程的技能框架</title>
        <link>https://knightli.com/2026/05/15/obra-superpowers-agentic-skills-framework/</link>
        <pubDate>Fri, 15 May 2026 08:53:17 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/15/obra-superpowers-agentic-skills-framework/</guid>
        <description>&lt;p&gt;&lt;code&gt;obra/superpowers&lt;/code&gt; 是一个给 coding agent 使用的技能框架，也是一套软件开发方法论。它的目标不是再写一个“让 AI 更听话”的万能 prompt，而是把 agent 的工作流程固定下来：先澄清目标，再产出设计，再拆计划，再按测试驱动开发推进，最后做 review 和收尾。&lt;/p&gt;
&lt;p&gt;项目地址：&lt;a class=&#34;link&#34; href=&#34;https://github.com/obra/superpowers&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/obra/superpowers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;截至写作时，GitHub API 显示这个仓库已有超过 19 万 star，许可证为 MIT，最近仍在更新。README 对它的描述很直接：&lt;code&gt;An agentic skills framework &amp;amp; software development methodology that works.&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;它想解决什么问题&#34;&gt;它想解决什么问题
&lt;/h2&gt;&lt;p&gt;现在很多 AI 编程工具的问题，不是“不够会写代码”，而是太容易直接写代码。&lt;/p&gt;
&lt;p&gt;用户刚说一个模糊需求，agent 就开始改文件；改完以后看似完成，其实边界没对齐、测试没补、架构没想清楚。短任务可能没事，复杂项目里就会变成返工、回滚和技术债。&lt;/p&gt;
&lt;p&gt;Superpowers 的思路是：让 agent 在动手前先进入流程。&lt;/p&gt;
&lt;p&gt;README 里描述的核心路径大致是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;发现用户要做东西时，不立刻写代码，而是先追问目标。&lt;/li&gt;
&lt;li&gt;从对话中整理出规格说明，并分段给用户确认。&lt;/li&gt;
&lt;li&gt;设计通过后，生成足够清楚的实施计划。&lt;/li&gt;
&lt;li&gt;用户说 “go” 之后，再进入实现流程。&lt;/li&gt;
&lt;li&gt;实现时强调 TDD、YAGNI、DRY，并通过 review 检查结果。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这套流程听起来不新，但放到 coding agent 里很关键。AI 的执行速度越快，前置澄清和中途验证越重要。&lt;/p&gt;
&lt;h2 id=&#34;支持哪些工具&#34;&gt;支持哪些工具
&lt;/h2&gt;&lt;p&gt;Superpowers 不是只面向一个 agent。README 里列出的安装入口包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Claude Code&lt;/li&gt;
&lt;li&gt;Codex CLI&lt;/li&gt;
&lt;li&gt;Codex App&lt;/li&gt;
&lt;li&gt;Factory Droid&lt;/li&gt;
&lt;li&gt;Gemini CLI&lt;/li&gt;
&lt;li&gt;OpenCode&lt;/li&gt;
&lt;li&gt;Cursor&lt;/li&gt;
&lt;li&gt;GitHub Copilot CLI&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;其中 Codex CLI 和 Codex App 都可以通过官方 Codex plugin marketplace 安装。Claude Code 也可以通过官方插件市场或 Superpowers 自己的 marketplace 安装。&lt;/p&gt;
&lt;p&gt;这说明它的定位更像“跨 harness 的工作流层”，而不是绑定某一家模型或某一个命令行工具。&lt;/p&gt;
&lt;h2 id=&#34;基础工作流&#34;&gt;基础工作流
&lt;/h2&gt;&lt;p&gt;Superpowers 的基础工作流分成几个阶段。&lt;/p&gt;
&lt;p&gt;第一步是 &lt;code&gt;brainstorming&lt;/code&gt;。它会在写代码前触发，通过问题把粗糙想法整理成可执行设计。它不是让 agent 自嗨式补全需求，而是把设计分段拿给用户确认。&lt;/p&gt;
&lt;p&gt;第二步是 &lt;code&gt;using-git-worktrees&lt;/code&gt;。设计确认后，它会创建隔离的工作区和新分支，先确认项目能正常安装、测试基线是干净的。这一步能减少多个任务互相污染工作区的问题。&lt;/p&gt;
&lt;p&gt;第三步是 &lt;code&gt;writing-plans&lt;/code&gt;。它会把设计拆成短小任务，每个任务要求有明确文件路径、代码范围和验证步骤。README 里甚至把计划写给“没有上下文、品味可疑、不爱测试的热情初级工程师”也能执行，当作清晰度标准。&lt;/p&gt;
&lt;p&gt;第四步是实现。它可以用 &lt;code&gt;subagent-driven-development&lt;/code&gt; 派发子任务，也可以用 &lt;code&gt;executing-plans&lt;/code&gt; 分批执行。重点不是并发本身，而是每个任务都要能检查、能 review、能继续推进。&lt;/p&gt;
&lt;p&gt;第五步是 &lt;code&gt;test-driven-development&lt;/code&gt;。Superpowers 强调真正的 RED-GREEN-REFACTOR：先写失败测试，确认失败，再写最小实现，确认通过，然后重构。它甚至要求删除测试前写出来的实现代码，避免“先实现后补测试”的假 TDD。&lt;/p&gt;
&lt;p&gt;第六步是 &lt;code&gt;requesting-code-review&lt;/code&gt;。任务之间做 review，按严重程度报告问题。Critical 问题会阻塞继续推进。&lt;/p&gt;
&lt;p&gt;最后是 &lt;code&gt;finishing-a-development-branch&lt;/code&gt;。任务结束后，验证测试，给出合并、发 PR、保留或丢弃 worktree 的选择。&lt;/p&gt;
&lt;h2 id=&#34;skills-library-里有什么&#34;&gt;Skills Library 里有什么
&lt;/h2&gt;&lt;p&gt;Superpowers 的技能库可以分成几类。&lt;/p&gt;
&lt;p&gt;测试类主要是 &lt;code&gt;test-driven-development&lt;/code&gt;，围绕红绿重构循环，并包含测试反模式参考。&lt;/p&gt;
&lt;p&gt;调试类包括 &lt;code&gt;systematic-debugging&lt;/code&gt; 和 &lt;code&gt;verification-before-completion&lt;/code&gt;。前者要求按复现、最小化、假设、验证、修复的过程找根因；后者强调不要在没有验证前宣布完成。&lt;/p&gt;
&lt;p&gt;协作类更丰富，包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;brainstorming&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;writing-plans&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;executing-plans&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dispatching-parallel-agents&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;requesting-code-review&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;receiving-code-review&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;using-git-worktrees&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;finishing-a-development-branch&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;subagent-driven-development&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;元技能包括 &lt;code&gt;writing-skills&lt;/code&gt; 和 &lt;code&gt;using-superpowers&lt;/code&gt;。前者用于创建新技能，后者用于理解技能系统本身。&lt;/p&gt;
&lt;p&gt;这些技能组合起来，像是给 agent 装了一套工程习惯：什么时候该问，什么时候该计划，什么时候该测试，什么时候该停下来 review。&lt;/p&gt;
&lt;h2 id=&#34;和普通-prompt-最大的区别&#34;&gt;和普通 prompt 最大的区别
&lt;/h2&gt;&lt;p&gt;普通 prompt 往往把规则堆在一段 system prompt 里：不要乱改、先思考、要测试、要解释、要简洁。问题是规则越堆越多，模型越容易在复杂任务里选择性遗忘。&lt;/p&gt;
&lt;p&gt;Superpowers 更像把规则拆成可触发的流程模块。不同任务阶段使用不同技能，每个技能只负责一段工作。这样做有几个好处：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;规则更短，目标更集中。&lt;/li&gt;
&lt;li&gt;agent 更容易知道当前阶段该做什么。&lt;/li&gt;
&lt;li&gt;复杂流程可以被拆成可检查的步骤。&lt;/li&gt;
&lt;li&gt;技能可以跨工具复用。&lt;/li&gt;
&lt;li&gt;团队可以把自己的工程习惯沉淀成技能。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这也是它最值得参考的地方：不要只追求“更聪明的模型”，还要给模型一套可重复的工作方式。&lt;/p&gt;
&lt;h2 id=&#34;适合谁用&#34;&gt;适合谁用
&lt;/h2&gt;&lt;p&gt;Superpowers 更适合已经在认真使用 coding agent 的开发者，尤其是这些场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;任务不只是单文件改动。&lt;/li&gt;
&lt;li&gt;希望 agent 先设计再实现。&lt;/li&gt;
&lt;li&gt;项目需要 TDD 或至少需要验证步骤。&lt;/li&gt;
&lt;li&gt;经常并行做多个功能分支。&lt;/li&gt;
&lt;li&gt;希望用 subagent 分摊实现、检查和 review。&lt;/li&gt;
&lt;li&gt;想把团队流程写成可复用技能。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果只是让 AI 改一行配置、生成一个脚本，它可能显得偏重。但一旦任务涉及多文件、多阶段、多轮确认，它的流程约束就会变得有价值。&lt;/p&gt;
&lt;h2 id=&#34;使用时要注意什么&#34;&gt;使用时要注意什么
&lt;/h2&gt;&lt;p&gt;第一，不要把它理解成自动驾驶。Superpowers 能让 agent 更有流程感，但设计取舍、需求边界和最终验收仍然需要人负责。&lt;/p&gt;
&lt;p&gt;第二，TDD 和 review 会增加前期成本。小任务可能会变慢，但复杂任务通常能减少返工。&lt;/p&gt;
&lt;p&gt;第三，子代理并发不是越多越好。并发适合边界清楚、写入范围不重叠的任务；如果需求还没想清楚，先并发只会把混乱放大。&lt;/p&gt;
&lt;p&gt;第四，团队要维护自己的技能质量。技能不是写完就万事大吉，过时的流程、模糊的指令和互相冲突的规则，也会拖累 agent。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;Superpowers 的价值，不在于某个单独技能多神奇，而在于它把 coding agent 从“接到需求就写代码”拉回了软件工程流程。&lt;/p&gt;
&lt;p&gt;它提醒我们：AI 编程真正缺的往往不是生成速度，而是澄清、计划、验证、review 和收尾。模型越强，这些流程越不能省。否则 AI 只是更快地制造未验证的代码。&lt;/p&gt;
&lt;p&gt;如果你已经在用 Codex、Claude Code、Cursor 或 Gemini CLI 做真实项目，Superpowers 值得看一眼。即使不直接安装，它的技能拆分方式也很适合拿来改造自己的 agent 工作流。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>拒绝 Vibe Coding：Matt Pocock 的 skills 仓库给 AI 编程补上工程约束</title>
        <link>https://knightli.com/2026/05/15/matt-pocock-skills-ai-engineering-workflow/</link>
        <pubDate>Fri, 15 May 2026 08:46:23 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/15/matt-pocock-skills-ai-engineering-workflow/</guid>
        <description>&lt;p&gt;AI 写代码越快，项目失控也可能越快。真正的问题不是模型会不会生成函数，而是它是否理解需求、是否遵守团队语言、是否能在已有架构里小步推进。如果把 AI 当成“随便说一句就自动完工”的代码喷射器，最后很容易得到一堆跑不通、难维护、没人敢改的代码。&lt;/p&gt;
&lt;p&gt;Matt Pocock 开源的 &lt;code&gt;mattpocock/skills&lt;/code&gt; 仓库，正好给了一个相反方向的示例：不要让 AI 接管整个开发流程，而是把 AI 放进成熟的软件工程约束里。&lt;/p&gt;
&lt;p&gt;项目地址：&lt;a class=&#34;link&#34; href=&#34;https://github.com/mattpocock/skills&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/mattpocock/skills&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这套方法的重点不是某个神奇 prompt，而是一组可以组合的 agent skills。它们把需求澄清、领域建模、测试驱动、问题诊断、架构审查这些老派工程实践，重新包装成适合 AI 编程工具调用的工作流。&lt;/p&gt;
&lt;h2 id=&#34;先解决对齐失败&#34;&gt;先解决对齐失败
&lt;/h2&gt;&lt;p&gt;AI 编程最常见的失败，是你以为它懂了，其实它只是顺着你的模糊描述开始猜。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;grill-me&lt;/code&gt; 的思路就是反过来：在写代码之前，先让 AI 变成一个会追问的审稿人。它不会立刻开始实现，而是持续追问计划里的分支、边界和未决问题。&lt;/p&gt;
&lt;p&gt;比如你说“做一个登录页”，它应该先问：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;忘记密码怎么处理？&lt;/li&gt;
&lt;li&gt;是否支持第三方登录？&lt;/li&gt;
&lt;li&gt;登录失败时要显示什么错误？&lt;/li&gt;
&lt;li&gt;账号锁定、验证码、风控是否在本期范围内？&lt;/li&gt;
&lt;li&gt;成功后跳转到哪里？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这一步看起来慢，但它减少的是后面返工的时间。AI 生成代码的成本越低，需求没想清楚带来的浪费就越大。&lt;/p&gt;
&lt;h2 id=&#34;把领域语言写进上下文&#34;&gt;把领域语言写进上下文
&lt;/h2&gt;&lt;p&gt;第二个问题是 AI 的“通用词汇病”。它不了解团队内部的业务叫法，只能用常见词来猜，于是变量名、函数名、文档描述都开始漂移。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;grill-with-docs&lt;/code&gt; 解决的是这个问题。它不只是追问需求，还会结合项目里的 &lt;code&gt;CONTEXT.md&lt;/code&gt;、ADR 或领域文档，检查用户表达是否和既有术语冲突。确认后的术语、边界和决策，可以继续沉淀回上下文文档。&lt;/p&gt;
&lt;p&gt;这和领域驱动设计里的“统一语言”很接近。假设团队把 user 称为 customer，把 order 称为 transaction，那么 AI 在写代码时也应该继承这些叫法，而不是自己再发明一套。&lt;/p&gt;
&lt;p&gt;上下文文档的价值不在于堆资料，而在于让 AI 少猜一点。&lt;/p&gt;
&lt;h2 id=&#34;用-tdd-限制生成速度&#34;&gt;用 TDD 限制生成速度
&lt;/h2&gt;&lt;p&gt;AI 的危险之处在于它太快了。过去写出一大段坏代码需要时间，现在几秒钟就能生成几百行。速度本身不是问题，缺少反馈循环才是问题。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;tdd&lt;/code&gt; skill 把经典的红绿重构流程放回 AI 编程里：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先为一个行为写失败测试。&lt;/li&gt;
&lt;li&gt;再实现刚好让测试通过的代码。&lt;/li&gt;
&lt;li&gt;然后重构。&lt;/li&gt;
&lt;li&gt;按垂直切片继续推进。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;重点是“一次一个行为”，而不是让 AI 一口气写完所有测试和所有实现。这样做可以把任务切小，也能让每一步都有可验证结果。AI 负责执行，人类负责确认方向和边界。&lt;/p&gt;
&lt;h2 id=&#34;用诊断循环处理复杂问题&#34;&gt;用诊断循环处理复杂问题
&lt;/h2&gt;&lt;p&gt;遇到 bug 时，很多 AI 会直接猜答案，然后连续改几轮，把问题越修越乱。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;diagnose&lt;/code&gt; 的价值在于要求 AI 先建立反馈循环：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;复现问题&lt;/li&gt;
&lt;li&gt;最小化场景&lt;/li&gt;
&lt;li&gt;提出假设&lt;/li&gt;
&lt;li&gt;增加观测或日志&lt;/li&gt;
&lt;li&gt;修复&lt;/li&gt;
&lt;li&gt;补回归测试&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这套流程不新，但在 AI 编程里尤其重要。因为 AI 很擅长快速尝试，却不一定擅长判断哪次尝试真正接近根因。诊断流程相当于给它加了一条轨道。&lt;/p&gt;
&lt;h2 id=&#34;定期审查架构而不是只看单个任务&#34;&gt;定期审查架构，而不是只看单个任务
&lt;/h2&gt;&lt;p&gt;单次任务跑通，不代表代码库变好了。AI 反复提交小改动后，最容易出现的问题是模块边界变模糊、接口越来越复杂、测试越来越难写。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;improve-codebase-architecture&lt;/code&gt; 这类 skill 的意义，是让 AI 定期跳出当前任务，从更高层看代码库：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;哪些模块职责开始混在一起？&lt;/li&gt;
&lt;li&gt;哪些接口太复杂？&lt;/li&gt;
&lt;li&gt;哪些路径难以测试？&lt;/li&gt;
&lt;li&gt;哪些命名和领域语言不一致？&lt;/li&gt;
&lt;li&gt;哪些重复逻辑应该收敛？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这不是让 AI 自动大重构，而是让它先给出结构化观察和改进方向。真正要不要改、改到什么程度，仍然需要开发者判断。&lt;/p&gt;
&lt;h2 id=&#34;真正该限制的是自由度&#34;&gt;真正该限制的是自由度
&lt;/h2&gt;&lt;p&gt;这套方法论的核心可以压缩成一句话：AI 编程不是放任模型自由发挥，而是给它清晰的目标、上下文、测试和停止条件。&lt;/p&gt;
&lt;p&gt;人类更适合负责问题定义、架构边界、业务取舍和验收标准；AI 更适合负责代码生成、测试补全、重复修改和局部重构。两者配合得好，AI 是放大器；配合得不好，它会把混乱也一起放大。&lt;/p&gt;
&lt;p&gt;所以，软件工程基础没有因为 AI 变强而过时。恰恰相反，需求澄清、领域语言、TDD、诊断、架构审查这些能力，在 AI 时代变得更关键。&lt;/p&gt;
&lt;p&gt;会写代码的人会越来越多。真正拉开差距的，是谁能把 AI 放进可维护、可验证、可长期演进的工程体系里。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Codex /goal vs Claude Code /goal：长任务自动跑到完成</title>
        <link>https://knightli.com/2026/05/14/codex-goal-vs-claude-code-goal/</link>
        <pubDate>Thu, 14 May 2026 22:22:42 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/14/codex-goal-vs-claude-code-goal/</guid>
        <description>&lt;p&gt;&lt;code&gt;/goal&lt;/code&gt; 正在变成 AI 编程工具里的一个重要命令。&lt;/p&gt;
&lt;p&gt;它解决的不是“让模型多写几行代码”，而是另一个更实际的问题：当任务有明确完成条件时，能不能让 Agent 持续推进，直到条件满足，而不是每完成一轮就停下来等用户继续催。&lt;/p&gt;
&lt;p&gt;Codex CLI 已经在官方文档里加入了实验性的 &lt;code&gt;/goal&lt;/code&gt;。Claude Code 也上线了自己的 &lt;code&gt;/goal&lt;/code&gt; 文档，而且把它描述成一种可以跨多轮持续工作的自动化能力。两者名字一样，但产品取向并不完全一样。&lt;/p&gt;
&lt;h2 id=&#34;goal-到底解决什么问题&#34;&gt;&lt;code&gt;/goal&lt;/code&gt; 到底解决什么问题
&lt;/h2&gt;&lt;p&gt;普通 AI 编程对话通常是“一问一答”：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用户提出任务。&lt;/li&gt;
&lt;li&gt;Agent 分析、改代码、跑测试。&lt;/li&gt;
&lt;li&gt;Agent 汇报结果。&lt;/li&gt;
&lt;li&gt;用户再决定下一步。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这个流程适合短任务，但遇到迁移、重构、测试修复、issue backlog 清理时，就会变得很碎。Agent 可能每次只推进一小段，然后停下来等你输入“继续”。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/goal&lt;/code&gt; 的思路是把任务从“下一步做什么”改成“最终什么状态算完成”。例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/goal 完成登录模块迁移，所有 auth 测试通过，lint 无报错
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这类目标天然适合长任务，因为它有清楚的终点：测试通过、构建成功、文件拆分完成、队列清空、验收条件满足。&lt;/p&gt;
&lt;h2 id=&#34;codex-的-goal实验功能绑定当前线程&#34;&gt;Codex 的 &lt;code&gt;/goal&lt;/code&gt;：实验功能，绑定当前线程
&lt;/h2&gt;&lt;p&gt;OpenAI 的 Codex CLI 文档把 &lt;code&gt;/goal&lt;/code&gt; 标为实验功能。它不是默认稳定能力，需要先开启 &lt;code&gt;features.goals&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;开启方式有两种：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/experimental
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;或者在 &lt;code&gt;config.toml&lt;/code&gt; 里加入：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;features&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;goals&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;启用后，可以这样使用：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/goal Finish the migration and keep tests green
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;常用命令包括：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/goal
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/goal pause
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/goal resume
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/goal clear
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;按照 OpenAI 文档的说法，Codex 会把 goal 附着在当前 active thread 上，在更大的任务运行过程中持续跟踪这个目标。&lt;/p&gt;
&lt;p&gt;这里要注意一个细节：官方文档对 Codex &lt;code&gt;/goal&lt;/code&gt; 的措辞比较克制。它强调“给长任务设置实验性目标”“把目标附着到当前线程”，但没有像 Claude Code 文档那样展开说明每一轮结束后由独立 evaluator 自动判断并继续下一轮。所以现在使用 Codex &lt;code&gt;/goal&lt;/code&gt; 时，最好仍把它看作实验中的长任务目标机制，而不是完全稳定的无人值守执行模式。&lt;/p&gt;
&lt;h2 id=&#34;claude-code-的-goal完成条件驱动的多轮执行&#34;&gt;Claude Code 的 &lt;code&gt;/goal&lt;/code&gt;：完成条件驱动的多轮执行
&lt;/h2&gt;&lt;p&gt;Claude Code 的 &lt;code&gt;/goal&lt;/code&gt; 文档写得更明确：用户设置 completion condition 后，Claude 会跨 turn 持续工作，直到条件满足。&lt;/p&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/goal all tests in test/auth pass and the lint step is clean
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Claude Code 的机制大致是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当前 turn 完成后，不直接把控制权还给用户。&lt;/li&gt;
&lt;li&gt;一个小型快速模型会检查目标条件是否已经满足。&lt;/li&gt;
&lt;li&gt;如果没有满足，Claude 自动开始下一轮。&lt;/li&gt;
&lt;li&gt;如果满足，goal 自动清除，并在 transcript 里记录完成状态。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这意味着 Claude Code 的 &lt;code&gt;/goal&lt;/code&gt; 更像“按完成条件自动续跑”。它不只是把目标挂在会话里，而是把“是否继续下一轮”交给一个独立评估步骤。&lt;/p&gt;
&lt;p&gt;Claude Code 还支持直接查看状态：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/goal
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;状态里会显示目标条件、运行时间、已评估 turn 数、token 消耗，以及 evaluator 最近一次给出的原因。&lt;/p&gt;
&lt;p&gt;如果要提前停止，可以使用：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/goal clear
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;stop&lt;/code&gt;、&lt;code&gt;off&lt;/code&gt;、&lt;code&gt;reset&lt;/code&gt;、&lt;code&gt;none&lt;/code&gt;、&lt;code&gt;cancel&lt;/code&gt; 也可以作为清除别名。开启目标后，如果会话中断，之后通过 &lt;code&gt;--resume&lt;/code&gt; 或 &lt;code&gt;--continue&lt;/code&gt; 恢复时，仍然 active 的 goal 可以被带回来；但计时、turn 数和 token 基线会重新计算。&lt;/p&gt;
&lt;h2 id=&#34;两者最大的差异&#34;&gt;两者最大的差异
&lt;/h2&gt;&lt;p&gt;Codex 和 Claude Code 都在把 AI 编程从“单轮回答”推向“长任务执行”，但 &lt;code&gt;/goal&lt;/code&gt; 的定位有差异。&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;对比项&lt;/th&gt;
          &lt;th&gt;Codex CLI &lt;code&gt;/goal&lt;/code&gt;&lt;/th&gt;
          &lt;th&gt;Claude Code &lt;code&gt;/goal&lt;/code&gt;&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;状态&lt;/td&gt;
          &lt;td&gt;experimental&lt;/td&gt;
          &lt;td&gt;官方文档单独成页说明&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;启用方式&lt;/td&gt;
          &lt;td&gt;需要开启 &lt;code&gt;features.goals&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;可直接在受信任 workspace 使用&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;目标作用域&lt;/td&gt;
          &lt;td&gt;当前 active thread&lt;/td&gt;
          &lt;td&gt;当前 session&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;常用操作&lt;/td&gt;
          &lt;td&gt;set / view / pause / resume / clear&lt;/td&gt;
          &lt;td&gt;set / view / clear&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;自动判断&lt;/td&gt;
          &lt;td&gt;文档强调目标附着与跟踪&lt;/td&gt;
          &lt;td&gt;明确说明每轮后由 evaluator 判断&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;自动续跑&lt;/td&gt;
          &lt;td&gt;文档表述较克制&lt;/td&gt;
          &lt;td&gt;条件未满足时自动下一轮&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;适合场景&lt;/td&gt;
          &lt;td&gt;想在 Codex 长任务里保持目标上下文&lt;/td&gt;
          &lt;td&gt;想按完成条件让 Claude Code 持续推进&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;简单说，Codex 的 &lt;code&gt;/goal&lt;/code&gt; 更像“给当前线程挂一个实验性的长期目标”；Claude Code 的 &lt;code&gt;/goal&lt;/code&gt; 更像“给当前会话设置一个可验证的停止条件，让它自动干到满足为止”。&lt;/p&gt;
&lt;h2 id=&#34;写好-goal-的关键&#34;&gt;写好 &lt;code&gt;/goal&lt;/code&gt; 的关键
&lt;/h2&gt;&lt;p&gt;不管使用哪一个工具，&lt;code&gt;/goal&lt;/code&gt; 都不适合写成模糊愿望。&lt;/p&gt;
&lt;p&gt;不太好的写法：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/goal 把项目优化一下
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;更好的写法：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/goal 将 payment 模块迁移到新 API，npm test -- payment 退出码为 0，git diff 只包含 payment 相关文件
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;一个好目标通常包含三点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;明确的完成状态。&lt;/li&gt;
&lt;li&gt;可执行的验证方式。&lt;/li&gt;
&lt;li&gt;必须遵守的边界。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果目标太大，还应该加上停止条件：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/goal 修复 eslint 报错，npm run lint 退出码为 0；如果超过 20 轮仍未完成，停止并总结剩余问题
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这很重要。&lt;code&gt;/goal&lt;/code&gt; 越强，越需要边界。否则 Agent 可能会为了追求“完成”而改动过多文件、跑太久、消耗太多 token，甚至把原本该停下来询问的问题继续往前推。&lt;/p&gt;
&lt;h2 id=&#34;什么时候适合用-goal&#34;&gt;什么时候适合用 &lt;code&gt;/goal&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;适合：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;测试修复：直到指定测试通过。&lt;/li&gt;
&lt;li&gt;代码迁移：直到所有调用点改完并编译成功。&lt;/li&gt;
&lt;li&gt;批量清理：直到某类 lint 或类型错误清零。&lt;/li&gt;
&lt;li&gt;文档补齐：直到所有指定模块都有说明。&lt;/li&gt;
&lt;li&gt;issue 队列处理：直到某个标签下的问题都被处理或明确分类。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不适合：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需求本身还没想清楚。&lt;/li&gt;
&lt;li&gt;需要频繁产品判断。&lt;/li&gt;
&lt;li&gt;涉及高风险删除、数据迁移或权限变更。&lt;/li&gt;
&lt;li&gt;验收条件只能靠主观判断。&lt;/li&gt;
&lt;li&gt;任务会跨越大量无关模块。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一个实用原则是：如果你能写出“跑哪个命令、看到什么结果、哪些文件不能碰”，就适合用 &lt;code&gt;/goal&lt;/code&gt;。如果只能写“帮我做得更好”，那还是先用普通对话、计划模式或人工评审更稳。&lt;/p&gt;
&lt;h2 id=&#34;对-ai-编程工具的影响&#34;&gt;对 AI 编程工具的影响
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;/goal&lt;/code&gt; 代表一个很明显的方向：AI 编程工具正在从“交互式助手”变成“可持续执行的工作单元”。&lt;/p&gt;
&lt;p&gt;过去我们让 Agent 做任务，经常要在旁边守着。它卡住了要提示，测完了要继续，报错了要再下命令。&lt;code&gt;/goal&lt;/code&gt; 把这部分交互压缩成一个完成条件，让 Agent 自己决定下一轮该做什么。&lt;/p&gt;
&lt;p&gt;但这也带来新的要求。以后写 prompt 不只是描述任务，还要写验收条件、验证命令、修改边界和停止规则。换句话说，用户的工作从“催它继续”变成“定义什么叫完成”。&lt;/p&gt;
&lt;p&gt;Codex 和 Claude Code 走到 &lt;code&gt;/goal&lt;/code&gt; 这一步，说明长任务 Agent 已经不再只是后台任务或云端队列的专利。终端里的本地编程工具，也开始需要更强的自主推进能力。&lt;/p&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结
&lt;/h2&gt;&lt;p&gt;Codex CLI 和 Claude Code 都有了 &lt;code&gt;/goal&lt;/code&gt;，但现阶段不要把它们简单看成同一个功能。&lt;/p&gt;
&lt;p&gt;Codex 的 &lt;code&gt;/goal&lt;/code&gt; 仍是实验能力，需要开启 &lt;code&gt;features.goals&lt;/code&gt;，更适合在 Codex 当前线程里维持长期目标。Claude Code 的 &lt;code&gt;/goal&lt;/code&gt; 则更明确地把“完成条件”和“自动续跑”连在一起，通过独立 evaluator 判断是否继续。&lt;/p&gt;
&lt;p&gt;对日常开发来说，这类命令最适合处理有明确验收标准的工程任务。它不会替代需求判断，也不会消除代码审查，但能减少长任务里大量重复的“继续”“再跑一次”“修到测试通过”。&lt;/p&gt;
&lt;p&gt;真正要学会的不是某个命令本身，而是如何把任务写成清楚、可验证、可停止的目标。&lt;/p&gt;
&lt;h2 id=&#34;参考资料&#34;&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;OpenAI Codex CLI Slash Commands：&lt;a class=&#34;link&#34; href=&#34;https://developers.openai.com/codex/cli/slash-commands&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://developers.openai.com/codex/cli/slash-commands&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Claude Code Goal 文档：&lt;a class=&#34;link&#34; href=&#34;https://code.claude.com/docs/en/goal&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://code.claude.com/docs/en/goal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Codex 怎么接入国产大模型？用 CCX 统一管理 OpenAI 兼容 API</title>
        <link>https://knightli.com/2026/05/13/ccx-ai-api-proxy-gateway/</link>
        <pubDate>Wed, 13 May 2026 23:20:40 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/13/ccx-ai-api-proxy-gateway/</guid>
        <description>&lt;p&gt;CCX 是一个 AI API 代理与协议转换网关。它把 Claude Messages、OpenAI Chat Completions、OpenAI Images、Codex Responses 和 Gemini API 放到同一个服务入口下，同时提供 Web 管理界面，用来配置渠道、密钥、模型映射、优先级、故障转移和流量监控。&lt;/p&gt;
&lt;p&gt;如果你平时同时使用 Claude、OpenAI、Gemini、Codex，或者维护多个兼容 OpenAI API 的上游服务，CCX 的价值就在于统一入口和统一管理。客户端只需要连接一个服务地址，后面的上游渠道由 CCX 负责调度。&lt;/p&gt;
&lt;p&gt;项目地址：&lt;a class=&#34;link&#34; href=&#34;https://github.com/BenedictKing/ccx&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/BenedictKing/ccx&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;ccx-解决什么问题&#34;&gt;CCX 解决什么问题
&lt;/h2&gt;&lt;p&gt;多个 AI API 混用时，最容易遇到几个问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个供应商的接口路径、鉴权方式、请求格式都不一样。&lt;/li&gt;
&lt;li&gt;同一类模型可能有多个上游，需要手动切换 base URL 和 API key。&lt;/li&gt;
&lt;li&gt;某个 key 或渠道失败后，客户端通常不会自动换备用渠道。&lt;/li&gt;
&lt;li&gt;团队使用时，很难集中管理模型白名单、代理、自定义请求头和调用日志。&lt;/li&gt;
&lt;li&gt;想同时接 Claude、Gemini、OpenAI Chat、图像接口和 Codex Responses 时，配置会越来越散。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CCX 的思路是把这些差异收敛到一个代理层。前端工具、脚本或业务服务只访问 CCX；CCX 再根据接口类型、模型、渠道状态、优先级和健康情况，把请求转发到合适的上游。&lt;/p&gt;
&lt;h2 id=&#34;支持哪些接口&#34;&gt;支持哪些接口
&lt;/h2&gt;&lt;p&gt;CCX 对外提供一个统一后端入口，默认端口是 &lt;code&gt;3000&lt;/code&gt;。主要路径包括：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;GET  /                         -&amp;gt; Web 管理界面
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;GET  /health                   -&amp;gt; 健康检查
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/api/*                         -&amp;gt; 管理 API
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1/messages              -&amp;gt; Claude Messages 代理
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1/chat/completions      -&amp;gt; OpenAI Chat 代理
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1/responses             -&amp;gt; Codex Responses 代理
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1/images/generations    -&amp;gt; OpenAI Images 生成
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1/images/edits          -&amp;gt; OpenAI Images 编辑
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1/images/variations     -&amp;gt; OpenAI Images 变体
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;GET  /v1/models                -&amp;gt; 模型列表
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1beta/models/*          -&amp;gt; Gemini 代理
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;也就是说，它不是只代理一种协议，而是把常见 AI API 分成 Messages、Chat、Responses、Gemini、Images 几类渠道分别管理。不同协议之间不会共用同一套健康状态和日志空间，这对排查问题很重要。&lt;/p&gt;
&lt;h2 id=&#34;架构思路&#34;&gt;架构思路
&lt;/h2&gt;&lt;p&gt;CCX 使用 Go 后端加 Vue 3 前端。前端构建产物会嵌入后端二进制，因此可以做单端口部署：同一个服务既提供 Web UI，也提供管理 API 和代理 API。&lt;/p&gt;
&lt;p&gt;一次请求大致会经过这样的链路：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Client -&amp;gt; Auth Middleware -&amp;gt; Route Handler -&amp;gt; Channel Scheduler -&amp;gt; Provider / Converter -&amp;gt; Upstream API -&amp;gt; Metrics / Channel Logs -&amp;gt; Client Response
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;几个核心模块的分工可以这样理解：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;handlers&lt;/code&gt;：接收不同协议的请求和管理操作。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;providers&lt;/code&gt;：封装上游 API 的请求和响应处理。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;converters&lt;/code&gt;：处理 Responses 等场景下的协议转换。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scheduler&lt;/code&gt;：根据优先级、促销期、健康状态、熔断状态和会话亲和性选择渠道。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;metrics&lt;/code&gt;：记录请求量、成功率、延迟、日志和熔断状态。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config&lt;/code&gt;：维护运行时配置，支持热重载和备份。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这个设计的重点不是“把所有接口强行变成一种格式”，而是按协议类型分别代理，再在管理、调度、日志和认证层做统一。&lt;/p&gt;
&lt;h2 id=&#34;ccx-和-codexbridge-有什么区别&#34;&gt;CCX 和 CodexBridge 有什么区别
&lt;/h2&gt;&lt;p&gt;CCX 和 CodexBridge 都和 Codex、OpenAI 兼容接口有关，但它们解决的问题不一样。&lt;/p&gt;
&lt;p&gt;CodexBridge 更像一个专门的 Codex 桥接器。它的核心目标是把 Codex CLI/SDK 封装成 OpenAI 兼容的 &lt;code&gt;/v1/chat/completions&lt;/code&gt; 服务，让 OpenWebUI、Cherry Studio、脚本或其他 OpenAI 兼容客户端可以调用本地 Codex。也就是说，CodexBridge 的重点是“把 Codex 接出来”。&lt;/p&gt;
&lt;p&gt;CCX 更像一个统一 AI API 网关。它不只处理 Codex Responses，还同时支持 Claude Messages、OpenAI Chat、OpenAI Images 和 Gemini API，并提供 Web 管理界面、渠道优先级、故障转移、日志监控和多 key 管理。也就是说，CCX 的重点是“把多个模型和多个供应商统一管起来”。&lt;/p&gt;
&lt;p&gt;简单对比：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;对比项&lt;/th&gt;
          &lt;th&gt;CodexBridge&lt;/th&gt;
          &lt;th&gt;CCX&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;核心定位&lt;/td&gt;
          &lt;td&gt;Codex 本地桥接器&lt;/td&gt;
          &lt;td&gt;多协议 AI API 网关&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;主要目标&lt;/td&gt;
          &lt;td&gt;让 Codex 变成 OpenAI 兼容接口&lt;/td&gt;
          &lt;td&gt;统一管理 Claude、OpenAI、Gemini、Codex 等渠道&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;管理界面&lt;/td&gt;
          &lt;td&gt;侧重 API 服务本身&lt;/td&gt;
          &lt;td&gt;提供 Web 管理界面&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;多渠道调度&lt;/td&gt;
          &lt;td&gt;不是重点&lt;/td&gt;
          &lt;td&gt;支持渠道优先级、故障转移和日志监控&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;适合场景&lt;/td&gt;
          &lt;td&gt;本机或单服务调用 Codex&lt;/td&gt;
          &lt;td&gt;团队、多 key、多供应商、多协议统一入口&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;如果只是想把 Codex 接进 OpenWebUI 或 Cherry Studio，CodexBridge 更直接；如果想同时管理 Codex、Claude、Gemini、DeepSeek、Qwen、Kimi 等多个上游，CCX 更合适。&lt;/p&gt;
&lt;h2 id=&#34;快速部署&#34;&gt;快速部署
&lt;/h2&gt;&lt;p&gt;最简单的方式是下载二进制文件。下载后，在同目录创建 &lt;code&gt;.env&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PROXY_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;your-proxy-access-key
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PORT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ENABLE_WEB_UI&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;APP_UI_LANGUAGE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;zh-CN
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;启动后访问：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;http://localhost:3000
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果在 Windows 下从 WSL、Docker、PowerShell 或其他环境访问 &lt;code&gt;localhost&lt;/code&gt; 不通，可以改用 Windows 主机的局域网 IPv4 地址，例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;http://192.168.1.23:3000
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;CCX 默认通过 &lt;code&gt;:PORT&lt;/code&gt; 监听所有网卡地址，所以暴露到局域网时要注意访问控制。&lt;/p&gt;
&lt;h2 id=&#34;docker-部署&#34;&gt;Docker 部署
&lt;/h2&gt;&lt;p&gt;Docker 方式适合长期运行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker run -d &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --name ccx &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -p 3000:3000 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -e &lt;span class=&#34;nv&#34;&gt;PROXY_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;your-proxy-access-key &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -e &lt;span class=&#34;nv&#34;&gt;APP_UI_LANGUAGE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;zh-CN &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -v &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;pwd&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;/.config:/app/.config &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  crpi-i19l8zl0ugidq97v.cn-hangzhou.personal.cr.aliyuncs.com/bene/ccx:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果仓库里已经有 &lt;code&gt;docker-compose.yml&lt;/code&gt;，也可以直接：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;需要自动更新时，可以叠加 Watchtower 配置：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose -f docker-compose.yml -f docker-compose.watchtower.yml up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;部署完成后，&lt;code&gt;.config&lt;/code&gt; 目录会保存运行时配置和持久化数据，建议挂载到宿主机，避免容器重建后配置丢失。&lt;/p&gt;
&lt;h2 id=&#34;源码运行&#34;&gt;源码运行
&lt;/h2&gt;&lt;p&gt;开发或自定义构建可以走源码方式：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone https://github.com/BenedictKing/ccx
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; ccx
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cp backend-go/.env.example backend-go/.env
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;常用命令：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make dev
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make run
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make build
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make frontend-dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;前端单独开发：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; frontend
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun install
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun run dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;后端单独开发：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; backend-go
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;关键环境变量&#34;&gt;关键环境变量
&lt;/h2&gt;&lt;p&gt;最小可用配置通常包括：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PORT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ENV&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;production
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ENABLE_WEB_UI&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PROXY_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;your-proxy-access-key
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ADMIN_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;your-admin-secret-key
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;APP_UI_LANGUAGE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;zh-CN
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;LOG_LEVEL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;info
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;REQUEST_TIMEOUT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;300000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PROXY_ACCESS_KEY&lt;/code&gt; 用于代理 API，是必须修改的密钥。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ADMIN_ACCESS_KEY&lt;/code&gt; 用于 Web 管理界面和 &lt;code&gt;/api/*&lt;/code&gt;，建议和代理密钥分开。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ENABLE_WEB_UI&lt;/code&gt; 控制是否启用管理界面。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REQUEST_TIMEOUT&lt;/code&gt; 控制请求超时时间，长上下文或图像任务可以适当调大。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LOG_LEVEL&lt;/code&gt; 控制日志级别，生产环境一般用 &lt;code&gt;info&lt;/code&gt; 或 &lt;code&gt;warn&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果需要限制请求体大小，可以关注：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;MAX_REQUEST_BODY_SIZE_MB&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;50&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;图像编辑、base64 图片、多模态请求都可能让请求体变大。&lt;/p&gt;
&lt;h2 id=&#34;渠道编排和故障转移&#34;&gt;渠道编排和故障转移
&lt;/h2&gt;&lt;p&gt;CCX 的管理界面可以配置多个渠道，并为每个渠道设置：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上游服务类型。&lt;/li&gt;
&lt;li&gt;API key 或多 key 轮换。&lt;/li&gt;
&lt;li&gt;代理地址。&lt;/li&gt;
&lt;li&gt;自定义请求头。&lt;/li&gt;
&lt;li&gt;模型白名单。&lt;/li&gt;
&lt;li&gt;路由前缀。&lt;/li&gt;
&lt;li&gt;优先级。&lt;/li&gt;
&lt;li&gt;健康检查与熔断恢复。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;调度时会综合考虑渠道状态、优先级、促销期、Trace 亲和性、熔断状态和可用 key。简单理解：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;正常情况下，优先级高的渠道先被使用。&lt;/li&gt;
&lt;li&gt;某个渠道失败后，可以故障转移到备用渠道。&lt;/li&gt;
&lt;li&gt;熔断机制会避免持续打到明显不可用的上游。&lt;/li&gt;
&lt;li&gt;Trace 亲和性会尽量让同一类会话保持在合适的渠道上。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这类能力适合有多个 key、多个供应商或多个地区上游的场景。个人轻量使用时，也可以只配置一个渠道，把 CCX 当成带 Web UI 的代理层。&lt;/p&gt;
&lt;h2 id=&#34;日志和监控&#34;&gt;日志和监控
&lt;/h2&gt;&lt;p&gt;CCX 提供渠道指标和请求日志，可以看到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;请求量。&lt;/li&gt;
&lt;li&gt;成功率。&lt;/li&gt;
&lt;li&gt;失败率。&lt;/li&gt;
&lt;li&gt;平均延迟。&lt;/li&gt;
&lt;li&gt;按模型统计的历史数据。&lt;/li&gt;
&lt;li&gt;渠道状态和熔断情况。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;生产环境建议使用相对克制的日志配置：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ENV&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;production
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;LOG_LEVEL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;info
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ENABLE_REQUEST_LOGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ENABLE_RESPONSE_LOGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这样可以保留基本请求信息，又避免把完整响应内容写入日志。排查问题时可以临时打开更详细的日志，但完成后应恢复，尤其不要在生产环境长期输出请求体和响应体。&lt;/p&gt;
&lt;h2 id=&#34;安全建议&#34;&gt;安全建议
&lt;/h2&gt;&lt;p&gt;CCX 是代理网关，里面会保存上游 API key，所以部署时不要只追求“能跑起来”。至少要注意这些点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要使用默认或过短的 &lt;code&gt;PROXY_ACCESS_KEY&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;建议单独设置 &lt;code&gt;ADMIN_ACCESS_KEY&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;不要把 Web 管理界面直接暴露到公网。&lt;/li&gt;
&lt;li&gt;如果必须公网访问，建议放在反向代理、VPN、访问控制或单点登录之后。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.env&lt;/code&gt;、&lt;code&gt;.config&lt;/code&gt;、日志文件都不要提交到 Git 仓库。&lt;/li&gt;
&lt;li&gt;生产环境不要长期启用完整请求体和响应体日志。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可以用下面的方式生成随机密钥：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PROXY_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;openssl rand -base64 32&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ADMIN_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;openssl rand -base64 32&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;适合谁使用&#34;&gt;适合谁使用
&lt;/h2&gt;&lt;p&gt;CCX 更适合这些场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;同时维护 Claude、OpenAI、Gemini、Codex 或图像接口。&lt;/li&gt;
&lt;li&gt;有多个 API key，需要轮换、分流和故障转移。&lt;/li&gt;
&lt;li&gt;想用 Web UI 管理上游渠道，而不是手动改配置文件。&lt;/li&gt;
&lt;li&gt;想观察每个渠道的成功率、延迟和请求日志。&lt;/li&gt;
&lt;li&gt;想给团队提供一个统一 AI API 入口。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你只是本机偶尔调用一个模型，直接用官方 SDK 或单一 OpenAI 兼容代理会更简单。CCX 的优势主要在多渠道、多协议和统一运维。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;CCX 的定位是 AI API 网关，而不是某个模型的客户端。它把 Claude Messages、OpenAI Chat、OpenAI Images、Codex Responses 和 Gemini 放到一个代理层里，并提供渠道编排、故障转移、日志监控和 Web 管理界面。&lt;/p&gt;
&lt;p&gt;对个人用户来说，它可以减少切换 API 地址和密钥的麻烦；对团队或长期运行的服务来说，它更像一个轻量级 AI 网关。真正上线前，重点不只是配置模型，还要配置好密钥、管理入口、日志级别、渠道优先级和故障转移策略。&lt;/p&gt;
&lt;h2 id=&#34;参考&#34;&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;GitHub 项目：&lt;a class=&#34;link&#34; href=&#34;https://github.com/BenedictKing/ccx&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/BenedictKing/ccx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;架构说明：&lt;a class=&#34;link&#34; href=&#34;https://github.com/BenedictKing/ccx/blob/main/ARCHITECTURE.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/BenedictKing/ccx/blob/main/ARCHITECTURE.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;环境变量说明：&lt;a class=&#34;link&#34; href=&#34;https://github.com/BenedictKing/ccx/blob/main/ENVIRONMENT.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/BenedictKing/ccx/blob/main/ENVIRONMENT.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Codex 怎么接入国产大模型？OpenAI 兼容接口与 CodexBridge 使用思路</title>
        <link>https://knightli.com/2026/05/13/codexbridge-openai-compatible-api/</link>
        <pubDate>Wed, 13 May 2026 23:08:28 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/13/codexbridge-openai-compatible-api/</guid>
        <description>&lt;p&gt;CodexBridge 是一个本地桥接工具，目标很直接：把 Codex CLI/SDK 封装成 OpenAI 兼容的 HTTP 服务。这样一来，原本只能在终端里使用的 Codex，可以被 OpenWebUI、Cherry Studio、脚本、自动化系统或任何兼容 OpenAI Chat Completions 的客户端调用。&lt;/p&gt;
&lt;p&gt;它提供的核心接口是 &lt;code&gt;/v1/chat/completions&lt;/code&gt; 和 &lt;code&gt;/v1/models&lt;/code&gt;。前者负责对话，支持普通同步返回和 SSE 流式输出；后者让客户端能像读取模型列表一样发现可用模型。对已经接过 OpenAI API 的工具来说，这种设计的好处是改动小，通常只需要改 base URL、API key 和模型名。&lt;/p&gt;
&lt;p&gt;项目地址：&lt;a class=&#34;link&#34; href=&#34;https://github.com/begonia599/CodexBridge&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/begonia599/CodexBridge&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;适合什么场景&#34;&gt;适合什么场景
&lt;/h2&gt;&lt;p&gt;CodexBridge 适合想把 Codex 接入现有 AI 客户端或工作流的人。例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;想在 OpenWebUI、Cherry Studio 里直接选择 Codex 模型。&lt;/li&gt;
&lt;li&gt;想用 &lt;code&gt;curl&lt;/code&gt;、Python、Node.js 等脚本调用本机 Codex。&lt;/li&gt;
&lt;li&gt;想让同一个前端同时接 OpenAI、Ollama、其他兼容接口和 Codex。&lt;/li&gt;
&lt;li&gt;想保留 Codex 的本地线程、沙箱、工作目录和审批能力。&lt;/li&gt;
&lt;li&gt;想给内部工具提供一个统一的 &lt;code&gt;/v1/chat/completions&lt;/code&gt; 入口。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它不是一个新的大模型，也不是替代 Codex CLI 的完整前端。更准确地说，它是一个适配层：上游仍然是 Codex，本地桥接器负责把 OpenAI 风格的请求转换成 Codex 能理解的会话输入。&lt;/p&gt;
&lt;h2 id=&#34;基本环境&#34;&gt;基本环境
&lt;/h2&gt;&lt;p&gt;运行前需要准备：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Node.js 18 或更高版本。&lt;/li&gt;
&lt;li&gt;已安装并登录的 Codex CLI。&lt;/li&gt;
&lt;li&gt;npm，或者按自己的习惯换成 pnpm / yarn。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;源码部署的基本步骤如下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone https://github.com/begonia599/CodexBridge
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; codexbridge
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm install
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cp .env.example .env
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cp .env .env.local
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后编辑 &lt;code&gt;.env&lt;/code&gt; 或 &lt;code&gt;.env.local&lt;/code&gt;，设置 API key、默认模型、工作目录、沙箱模式、联网权限等配置。&lt;/p&gt;
&lt;p&gt;启动 HTTP 服务：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm run codex:server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;默认端口是 &lt;code&gt;8080&lt;/code&gt;，可以通过 &lt;code&gt;PORT&lt;/code&gt; 修改。服务启动后，可以访问：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;GET /health
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;POST /v1/chat/completions
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;GET /v1/models
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;cli-对话模式&#34;&gt;CLI 对话模式
&lt;/h2&gt;&lt;p&gt;除了 HTTP 服务，CodexBridge 也保留了一个轻量 CLI：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm run codex:chat
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;CLI 里可以直接输入自然语言与 Codex 对话。常用命令有两个：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/reset&lt;/code&gt;：创建新的 Codex 线程。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/exit&lt;/code&gt;：退出 CLI。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当前线程 ID 会保存在 &lt;code&gt;.codex_thread.json&lt;/code&gt;。下次启动 CLI 时，如果这个文件还在，就能继续之前的对话。&lt;/p&gt;
&lt;h2 id=&#34;http-调用示例&#34;&gt;HTTP 调用示例
&lt;/h2&gt;&lt;p&gt;最基础的请求可以这样写：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl http://localhost:8080/v1/chat/completions &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -H &lt;span class=&#34;s2&#34;&gt;&amp;#34;content-type: application/json&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -H &lt;span class=&#34;s2&#34;&gt;&amp;#34;authorization: Bearer 123321&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -d &lt;span class=&#34;s1&#34;&gt;&amp;#39;{&amp;#34;model&amp;#34;:&amp;#34;gpt-5-codex:medium&amp;#34;,&amp;#34;session_id&amp;#34;:&amp;#34;demo&amp;#34;,&amp;#34;messages&amp;#34;:[{&amp;#34;role&amp;#34;:&amp;#34;user&amp;#34;,&amp;#34;content&amp;#34;:&amp;#34;ls&amp;#34;}]}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里有几个点需要注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;authorization&lt;/code&gt; 里的 token 要和 &lt;code&gt;CODEX_BRIDGE_API_KEY&lt;/code&gt; 一致。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;model&lt;/code&gt; 可以带推理等级，例如 &lt;code&gt;gpt-5-codex:medium&lt;/code&gt; 或 &lt;code&gt;gpt-5-codex:high&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;session_id&lt;/code&gt; 用来绑定会话，方便复用同一个 Codex 线程。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果需要流式输出，加上 &lt;code&gt;stream: true&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -N http://localhost:8080/v1/chat/completions &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -H &lt;span class=&#34;s2&#34;&gt;&amp;#34;content-type: application/json&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -H &lt;span class=&#34;s2&#34;&gt;&amp;#34;authorization: Bearer 123321&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -d &lt;span class=&#34;s1&#34;&gt;&amp;#39;{&amp;#34;model&amp;#34;:&amp;#34;gpt-5-codex:high&amp;#34;,&amp;#34;session_id&amp;#34;:&amp;#34;stream&amp;#34;,&amp;#34;stream&amp;#34;:true,&amp;#34;messages&amp;#34;:[{&amp;#34;role&amp;#34;:&amp;#34;user&amp;#34;,&amp;#34;content&amp;#34;:&amp;#34;一步步介绍如何创建 Node.js 项目&amp;#34;}]}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;对支持 OpenAI 流式响应的客户端来说，这种返回方式更接近正常聊天体验。&lt;/p&gt;
&lt;h2 id=&#34;会话持久化怎么做&#34;&gt;会话持久化怎么做
&lt;/h2&gt;&lt;p&gt;CodexBridge 的一个重点是会话映射。请求里可以通过这些字段传入会话 ID：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;session_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conversation_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;thread_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;user&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也可以从请求头传：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;x-session-id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;session-id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x-conversation-id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x-thread-id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x-user-id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;生产环境建议开启：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CODEX_REQUIRE_SESSION_ID&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这样所有请求都必须带会话 ID，避免不同用户或不同聊天窗口混到同一个临时上下文里。会话映射保存在 &lt;code&gt;.codex_threads.json&lt;/code&gt;，删除这个文件可以重置桥接层的映射关系；Codex 自身线程仍然保存在 &lt;code&gt;~/.codex/sessions&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;如果 &lt;code&gt;CODEX_REQUIRE_SESSION_ID=false&lt;/code&gt; 且请求没有提供会话 ID，桥接器会把当前 &lt;code&gt;messages&lt;/code&gt; 展开成一次性输入发给 Codex。这种方式适合临时调用，但不适合长期对话。&lt;/p&gt;
&lt;h2 id=&#34;多模态输入&#34;&gt;多模态输入
&lt;/h2&gt;&lt;p&gt;CodexBridge 支持 OpenAI 风格的内容块，并会把图片转换成 Codex 可用的 &lt;code&gt;local_image&lt;/code&gt; 输入。&lt;/p&gt;
&lt;p&gt;远程图片可以写成：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;image_url&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;image_url&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://example.com/demo.png&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;本地图片可以写成：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;local_image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;./images/demo.png&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;远程资源会先下载到临时目录，回合结束后清理。实际使用时要注意请求体大小，尤其是把图片转成 base64 发送时，可能需要增大 &lt;code&gt;CODEX_JSON_LIMIT&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;结构化输出&#34;&gt;结构化输出
&lt;/h2&gt;&lt;p&gt;如果客户端支持 &lt;code&gt;response_format&lt;/code&gt;，可以让 CodexBridge 映射到 Codex 的 &lt;code&gt;outputSchema&lt;/code&gt;。这适合让 Codex 返回固定 JSON 结构，例如检查结果、摘要、分类结果或自动化任务报告。&lt;/p&gt;
&lt;p&gt;最小思路是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;model&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;gpt-5-codex&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;session_id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;lint&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;response_format&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;json_schema&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;json_schema&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;lint_report&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;schema&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;object&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;properties&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;summary&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;string&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;status&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;string&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;enum&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ok&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;action_required&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;required&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;summary&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;status&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;additionalProperties&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;messages&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;role&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;检查 src/ 的 lint 问题，并以 JSON 返回结果&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;需要注意，&lt;code&gt;type: &amp;quot;json_schema&amp;quot;&lt;/code&gt; 必须提供 &lt;code&gt;schema&lt;/code&gt;，否则服务会直接返回 400。&lt;/p&gt;
&lt;h2 id=&#34;关键环境变量&#34;&gt;关键环境变量
&lt;/h2&gt;&lt;p&gt;常用配置可以分成几类。&lt;/p&gt;
&lt;p&gt;服务与鉴权：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PORT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CODEX_BRIDGE_API_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;123321&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CODEX_JSON_LIMIT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;10mb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;默认模型：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CODEX_MODEL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;gpt-5-codex
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CODEX_REASONING&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;medium
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Codex 运行环境：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CODEX_WORKDIR&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CODEX_SANDBOX_MODE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;read-only
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CODEX_APPROVAL_POLICY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;never
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CODEX_SKIP_GIT_CHECK&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;联网能力：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CODEX_NETWORK_ACCESS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CODEX_WEB_SEARCH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果只是给前端聊天用，默认关闭联网更稳。只有明确需要让 Codex 执行 &lt;code&gt;curl&lt;/code&gt;、&lt;code&gt;git clone&lt;/code&gt; 或使用 Web 搜索时，再单独打开对应开关。&lt;/p&gt;
&lt;h2 id=&#34;docker-和一键脚本&#34;&gt;Docker 和一键脚本
&lt;/h2&gt;&lt;p&gt;项目也提供 Docker 方式，适合想把服务常驻起来的场景：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose logs -f codexbridge
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;也可以用项目提供的 Linux 安装脚本：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -fsSL https://raw.githubusercontent.com/begonia599/CodexBridge/master/scripts/install.sh &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;脚本会安装依赖、克隆或更新仓库、复制 &lt;code&gt;.env.example&lt;/code&gt;，并通过 Docker Compose 启动服务。它需要 &lt;code&gt;sudo&lt;/code&gt; 权限，适合在干净服务器上快速部署。已经有复杂 Node.js、Docker 或 Codex 环境的机器，建议先读脚本内容再执行。&lt;/p&gt;
&lt;h2 id=&#34;常见问题&#34;&gt;常见问题
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;请求返回 413&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通常是请求体太大，常见于 base64 图片。可以增大：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CODEX_JSON_LIMIT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;20mb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;提示 API key 无效&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;检查请求头是否带了：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Authorization: Bearer &amp;lt;你的 CODEX_BRIDGE_API_KEY&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;或者使用 &lt;code&gt;x-api-key&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Codex 报 Git 仓库限制&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果运行目录不是可信仓库，可能会触发 Codex 的检查。只在确认安全的环境中使用：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CODEX_SKIP_GIT_CHECK&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;想清空会话&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;桥接层会话映射在 &lt;code&gt;.codex_threads.json&lt;/code&gt;，Codex 自身线程在 &lt;code&gt;~/.codex/sessions&lt;/code&gt;。停掉服务后删除对应文件或目录即可重置。&lt;/p&gt;
&lt;h2 id=&#34;使用建议&#34;&gt;使用建议
&lt;/h2&gt;&lt;p&gt;本地试用时，可以先用默认 API key 和 &lt;code&gt;read-only&lt;/code&gt; 沙箱跑通流程。确认 OpenWebUI、Cherry Studio 或脚本能正常调用后，再逐步调整 &lt;code&gt;CODEX_WORKDIR&lt;/code&gt;、&lt;code&gt;CODEX_SANDBOX_MODE&lt;/code&gt;、&lt;code&gt;CODEX_NETWORK_ACCESS&lt;/code&gt; 和 &lt;code&gt;CODEX_APPROVAL_POLICY&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;如果要给多人使用，建议至少做三件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;强制要求 &lt;code&gt;session_id&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;修改默认 API key。&lt;/li&gt;
&lt;li&gt;明确限制工作目录和沙箱权限。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CodexBridge 的价值不在于功能复杂，而在于把 Codex 放进了现有 OpenAI 兼容生态里。只要客户端能改 base URL，它就有机会把 Codex 当成一个普通聊天模型来接入，同时保留本地线程、沙箱和工具调用这些 Codex 自身的能力。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>ProgramBench 0% 解读：AI 编程真正可怕的不是失败，而是路线图清楚了</title>
        <link>https://knightli.com/2026/05/10/programbench-ai-coding-zero-percent/</link>
        <pubDate>Sun, 10 May 2026 12:32:39 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/10/programbench-ai-coding-zero-percent/</guid>
        <description>&lt;p&gt;AI 编程圈最近出现了一个新的基准测试：&lt;code&gt;ProgramBench&lt;/code&gt;。表面上看，它给出的结果很让程序员安心：九个主流模型在 fully resolved 指标上全部是 &lt;code&gt;0%&lt;/code&gt;，没有任何模型能完整通过一个任务。&lt;/p&gt;
&lt;p&gt;但这件事真正值得紧张的地方，不是今天的大模型还做不到，而是完整软件工程第一次被清楚地做成了一套可评测、可排名、可反复优化的题。&lt;/p&gt;
&lt;p&gt;一旦任务被定义清楚，AI 行业最擅长的事情就会发生：刷题、迭代、追榜，然后把原来做不到的事情一点点推到可用边缘。&lt;/p&gt;
&lt;h2 id=&#34;programbench-到底在测什么&#34;&gt;ProgramBench 到底在测什么
&lt;/h2&gt;&lt;p&gt;很多编程基准测试，测的是补函数、改 bug、通过单元测试，或者在已有项目里完成一个小功能。&lt;code&gt;ProgramBench&lt;/code&gt; 更狠，它不给源代码，也不给项目结构，更不给现成测试用例。&lt;/p&gt;
&lt;p&gt;它给模型的材料主要只有两类：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;一个已经编译好的可执行文件。&lt;/li&gt;
&lt;li&gt;这个程序的使用文档。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;模型需要自己运行可执行文件，观察输入输出行为，理解命令行参数、边界情况、错误信息、数据存储方式，然后重新实现一个行为一致的程序。&lt;/p&gt;
&lt;p&gt;这已经不是“写一段代码”，而是一个简化但完整的软件工程任务：要理解需求、探索行为、选择语言、设计结构、写源码、提供构建方式，并尽量通过隐藏测试。&lt;/p&gt;
&lt;p&gt;根据 ProgramBench 官方介绍，它目前包含 200 个任务，覆盖从小型命令行工具到 PHP、FFmpeg、SQLite 等大型真实项目。测试集由 agent-driven fuzzing 生成，总量超过 248,000 个行为测试。&lt;/p&gt;
&lt;p&gt;如果把测试流程拆开，ProgramBench 大致是在考四件事：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;读懂文档：理解程序应该提供哪些命令、参数和输出。&lt;/li&gt;
&lt;li&gt;探索行为：反复运行二进制程序，观察正常输入、异常输入和边界情况。&lt;/li&gt;
&lt;li&gt;重建实现：自己选择语言和项目结构，写出一个行为接近的替代程序。&lt;/li&gt;
&lt;li&gt;通过隐藏测试：不仅常规行为要对，错误处理、输出格式和边界条件也要尽量一致。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所以它的搜索价值不只是“又一个跑分”，而是回答一个更具体的问题：大模型能不能在没有源码的情况下，只靠文档和黑箱行为，从零复刻一个真实软件。&lt;/p&gt;
&lt;h2 id=&#34;为什么结果是-0&#34;&gt;为什么结果是 0%
&lt;/h2&gt;&lt;p&gt;ProgramBench 的主要指标是 fully resolved，也就是一个任务里的测试全部通过才算完成。当前 leaderboard 上，九个模型在这个指标上都是 &lt;code&gt;0%&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;参与测试的模型包括 Claude、GPT、Gemini 等系列，统一使用 &lt;code&gt;mini-SWE-agent&lt;/code&gt; 作为基线 agent。Claude Opus 4.7 在 almost resolved 指标上表现最好，大约有 &lt;code&gt;3.0%&lt;/code&gt; 的任务通过了至少 95% 的测试；Claude Opus 4.6 是 &lt;code&gt;2.5%&lt;/code&gt;，Claude Sonnet 4.6 是 &lt;code&gt;1.0%&lt;/code&gt;。GPT 5.4、GPT 5.4 mini、Gemini 3.1 Pro、Gemini 3 Flash 等在 almost resolved 上都是 &lt;code&gt;0.0%&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;这说明今天的大模型加一个轻量级 agent，还无法从零重建完整软件。即使是最简单的任务，也很难做到所有细节都完全对齐。&lt;/p&gt;
&lt;p&gt;但也要注意：这次测试用的是 &lt;code&gt;mini-SWE-agent&lt;/code&gt;，不是 Claude Code，也不是 Codex。换成更强的 coding agent、更多工具链支持、更长时间的探索流程，结果可能会提高。所以这个结果更准确的说法是：当前模型加轻量 agent，还不足以稳定完成完整软件重建。&lt;/p&gt;
&lt;h2 id=&#34;fully-resolved-和-almost-resolved-是什么意思&#34;&gt;fully resolved 和 almost resolved 是什么意思
&lt;/h2&gt;&lt;p&gt;读 ProgramBench 的结果时，最容易误解的是这两个指标。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fully resolved&lt;/code&gt; 是最严格的指标：一个任务里的所有隐藏测试都通过，才算完整解决。只要还漏掉一个边界条件、一个报错格式、一个命令参数行为，就不能算 fully resolved。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;almost resolved&lt;/code&gt; 则更像“接近完成”：如果一个任务至少通过了 95% 的测试，就算进入 almost resolved。它能反映模型有没有把大部分行为做出来，但还不能代表程序已经可以替代原软件。&lt;/p&gt;
&lt;p&gt;这也是为什么 &lt;code&gt;0%&lt;/code&gt; 要分开看。fully resolved 的 &lt;code&gt;0%&lt;/code&gt; 说明模型还无法完整交付；almost resolved 的差距则能看出哪些模型已经在部分任务上接近复刻成功。比如 Claude Opus 4.7 的 almost resolved 约为 &lt;code&gt;3.0%&lt;/code&gt;，说明它确实在少量相对简单的任务上更接近完成，但距离稳定重建完整软件仍然很远。&lt;/p&gt;
&lt;h2 id=&#34;为什么-mini-swe-agent-会影响测试结果&#34;&gt;为什么 mini-SWE-agent 会影响测试结果
&lt;/h2&gt;&lt;p&gt;这次测试使用统一的 &lt;code&gt;mini-SWE-agent&lt;/code&gt;，好处是公平：不同模型都跑在同一套轻量 agent 框架里，结果更容易横向比较。&lt;/p&gt;
&lt;p&gt;但它也会限制上限。完整软件重建不只取决于模型本身，还取决于 agent 是否会规划探索策略、是否能管理长期任务、是否会自动生成测试、是否能反复定位失败原因、是否能整理项目结构。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mini-SWE-agent&lt;/code&gt; 更像一个统一基线，而不是最强工程环境。Claude Code、Codex 这类更完整的 coding agent，通常会提供更强的工具调用、上下文组织、任务拆解和多轮修复能力。如果换成这些工具，结果可能会更好。&lt;/p&gt;
&lt;p&gt;所以 ProgramBench 这次结果更适合理解为：当前模型在轻量 agent 环境下还做不到完整软件重建。它不是在证明“模型永远做不到”，也不是在完整评估所有商业 coding agent 的上限。&lt;/p&gt;
&lt;h2 id=&#34;它和-swe-bench-的差别&#34;&gt;它和 SWE-bench 的差别
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;SWE-bench&lt;/code&gt; 已经是 AI 编程领域里很重要的基准。它让模型在真实 GitHub 仓库里读 issue、改代码、提交补丁，用来测试模型解决真实 bug 的能力。&lt;/p&gt;
&lt;p&gt;但 &lt;code&gt;SWE-bench&lt;/code&gt; 本质上仍然是在已有项目上修车：车还在，技术栈、目录结构、代码组织、架构设计都已经有人完成了。模型只需要找到问题，把坏掉的零件修好。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ProgramBench&lt;/code&gt; 更接近重新造车：你只知道这个车应该有什么行为，看到红灯会停、遇到行人会鸣笛，剩下的结构、语言、模块、构建方式，全都要自己决定。&lt;/p&gt;
&lt;p&gt;这就是为什么它难得多。它不再只考局部补丁能力，而是在考软件架构、系统推理、行为探索、自动测试、多轮纠错和长期工程设计。&lt;/p&gt;
&lt;p&gt;可以用一张表来理解两者差别：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;维度&lt;/th&gt;
          &lt;th&gt;SWE-bench&lt;/th&gt;
          &lt;th&gt;ProgramBench&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;起点&lt;/td&gt;
          &lt;td&gt;已有 GitHub 仓库和 issue&lt;/td&gt;
          &lt;td&gt;已编译可执行文件和使用文档&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;是否给源码&lt;/td&gt;
          &lt;td&gt;给源码&lt;/td&gt;
          &lt;td&gt;不给源码&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;主要任务&lt;/td&gt;
          &lt;td&gt;修复已有项目里的 bug&lt;/td&gt;
          &lt;td&gt;从行为重新实现一个完整程序&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;技术栈&lt;/td&gt;
          &lt;td&gt;原项目已经确定&lt;/td&gt;
          &lt;td&gt;模型自己选择&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;项目结构&lt;/td&gt;
          &lt;td&gt;原项目已经存在&lt;/td&gt;
          &lt;td&gt;模型自己设计&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;测试方式&lt;/td&gt;
          &lt;td&gt;提交补丁后跑测试&lt;/td&gt;
          &lt;td&gt;用隐藏行为测试验证复刻程度&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;主要考点&lt;/td&gt;
          &lt;td&gt;读代码、定位问题、补丁修复&lt;/td&gt;
          &lt;td&gt;行为探索、系统抽象、架构设计、完整实现&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这也是为什么 ProgramBench 更适合被看作下一阶段 AI Coding 的目标：它把“修现有代码”推进到了“重建完整软件”。&lt;/p&gt;
&lt;h2 id=&#34;0-并不等于安全&#34;&gt;0% 并不等于安全
&lt;/h2&gt;&lt;p&gt;看到 &lt;code&gt;0%&lt;/code&gt;，很多人的第一反应可能是：程序员饭碗暂时保住了。&lt;/p&gt;
&lt;p&gt;短期看，这句话没错。今天的大模型还不能稳定完成完整软件工程，尤其是在没有源码、没有测试用例、没有项目结构的情况下。需求澄清、架构设计、长期维护、安全控制、团队协作、业务理解，仍然是人类软件工程师的重要优势。&lt;/p&gt;
&lt;p&gt;但如果把 &lt;code&gt;0%&lt;/code&gt; 理解成“AI 编程到头了”，就太乐观了。&lt;/p&gt;
&lt;p&gt;ProgramBench 真正改变的是问题定义。以前大家知道 AI 可以补代码，也知道 AI 可以修 bug，但“从一个可执行文件和文档重建完整软件”这件事没有被清楚地放到统一赛道里。现在它被做成了 200 道题、统一评测、统一排名。&lt;/p&gt;
&lt;p&gt;这意味着模型公司、agent 公司、开发工具公司都知道下一步该往哪里发力：让 AI 从写代码片段，进化到维护、重建和交付完整软件系统。&lt;/p&gt;
&lt;h2 id=&#34;为什么要断网和防作弊&#34;&gt;为什么要断网和防作弊
&lt;/h2&gt;&lt;p&gt;ProgramBench 的设计里有一个细节很重要：它要防止模型作弊。&lt;/p&gt;
&lt;p&gt;早期测试中，模型会尝试直接从 GitHub 找源码，或者通过包管理器下载包含源码的包，甚至去系统缓存目录里翻找已经下载过的软件包。这样当然会破坏测试目的，因为问题就不再是“能不能从行为重建软件”，而是“能不能找到原始源码”。&lt;/p&gt;
&lt;p&gt;所以 ProgramBench 使用了沙箱和断网环境，不允许访问互联网，也不允许反编译、反汇编或读取可执行文件内容。模型只能执行程序，观察行为，再自己实现。&lt;/p&gt;
&lt;p&gt;这个限制让测试更干净，也更接近它真正想回答的问题：大语言模型能不能从程序行为和文档出发，自己构建一个可运行的软件项目。&lt;/p&gt;
&lt;h2 id=&#34;更值得警惕的是代码形态变化&#34;&gt;更值得警惕的是代码形态变化
&lt;/h2&gt;&lt;p&gt;ProgramBench 还有一个比 &lt;code&gt;0%&lt;/code&gt; 更值得软件工程师思考的发现：模型生成的代码往往不像人类工程师会写的项目。&lt;/p&gt;
&lt;p&gt;公开材料里提到，模型倾向于生成更少的文件、更浅的目录、更少的函数，以及更长的单个函数。也就是说，它可能写出一个巨大的、能跑的脚本，而不是一个结构清晰、便于人类维护的软件工程项目。&lt;/p&gt;
&lt;p&gt;从传统软件工程角度看，这通常是很差的代码。文件太少、函数太长、抽象不足、模块边界不清，都会让人类难以维护。&lt;/p&gt;
&lt;p&gt;但问题在于，AI 未必需要按照人类维护代码的方式写代码。&lt;/p&gt;
&lt;p&gt;人类强调抽象、命名、目录结构和模块边界，主要是因为人类记忆有限、团队需要协作、代码需要长期复用。AI 如果可以用更长上下文、检索系统和自动测试反复重写代码，它可能并不那么需要人类熟悉的这些工程规范。&lt;/p&gt;
&lt;p&gt;这会带来一个很现实的风险：未来 AI 写出的软件也许能跑、甚至很快，但人类越来越难插手维护。&lt;/p&gt;
&lt;h2 id=&#34;程序员真正要升级什么&#34;&gt;程序员真正要升级什么
&lt;/h2&gt;&lt;p&gt;ProgramBench 的结果对程序员不是简单的好消息，也不是简单的坏消息。&lt;/p&gt;
&lt;p&gt;短期看，完整软件工程仍然很难，程序员不会因为这次 benchmark 立刻失业。尤其是架构判断、需求澄清、安全把控、质量验收和业务理解，仍然需要人类负责。&lt;/p&gt;
&lt;p&gt;长期看，程序员的工作会继续上移。真正危险的不是“不会写代码”的人，而是只会写代码、但不会定义问题、验证结果、组织工具链和控制风险的人。&lt;/p&gt;
&lt;p&gt;未来的软件工程师可能更像：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;需求定义者：把模糊业务问题变成可执行目标。&lt;/li&gt;
&lt;li&gt;系统验收者：判断 AI 生成结果是否真的满足需求。&lt;/li&gt;
&lt;li&gt;工具链组织者：组合模型、agent、测试、部署和监控。&lt;/li&gt;
&lt;li&gt;质量负责人：控制安全、可维护性、边界条件和长期风险。&lt;/li&gt;
&lt;li&gt;业务和技术之间的翻译者：把真实问题转成工程系统能处理的约束。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果 AI 真的从代码助手变成完整软件工程师，人类程序员的价值就不再只是亲手写每一行代码，而是定义什么值得写、怎样算写对、哪里不能出错。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;ProgramBench 的 &lt;code&gt;0%&lt;/code&gt; 不是终点，而是新阶段的起点。&lt;/p&gt;
&lt;p&gt;它说明今天的大模型还不能从零稳定重建完整软件系统；但它也把下一代 AI Coding agent 的目标定义得非常清楚：从局部补丁走向完整项目，从代码片段走向系统交付。&lt;/p&gt;
&lt;p&gt;对程序员来说，短期可以松一口气，但长期不能只盯着“AI 现在还不行”。更重要的是尽快把自己从代码执行者升级为问题定义者、结果验收者和风险控制者。&lt;/p&gt;
&lt;p&gt;真正值得紧张的不是 AI 今天考了 &lt;code&gt;0%&lt;/code&gt;，而是题目已经摆出来了。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>GPT-5.5、GPT-5.4 与 GPT-5.3-Codex 如何取舍</title>
        <link>https://knightli.com/2026/05/10/gpt-5-5-vs-gpt-5-4-vs-gpt-5-3-codex/</link>
        <pubDate>Sun, 10 May 2026 08:43:17 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/10/gpt-5-5-vs-gpt-5-4-vs-gpt-5-3-codex/</guid>
        <description>&lt;p&gt;如果只看一句话，结论其实很直接：默认选 &lt;code&gt;GPT-5.5&lt;/code&gt;，预算更敏感或任务难度中等时选 &lt;code&gt;GPT-5.4&lt;/code&gt;，只有在 Codex 环境里做更长时间的软件工程任务，或者需要 Cloud Tasks、Code Review 这类能力时，再重点看 &lt;code&gt;GPT-5.3-Codex&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;这个判断不只是主观体验，OpenAI 在 Codex 官方文档里的推荐也已经比较明确。到 &lt;code&gt;2026-05-10&lt;/code&gt; 为止，Codex 文档仍然写着：大多数任务优先从 &lt;code&gt;gpt-5.5&lt;/code&gt; 开始；如果还没有开放 &lt;code&gt;gpt-5.5&lt;/code&gt;，继续用 &lt;code&gt;gpt-5.4&lt;/code&gt;；轻量任务或子任务则更适合 &lt;code&gt;gpt-5.4-mini&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;三个模型的定位差异&#34;&gt;三个模型的定位差异
&lt;/h2&gt;&lt;p&gt;先看官方定位。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.5&lt;/code&gt; 是 Codex 里的最新前沿模型，面向复杂编程、电脑操作、知识工作和研究型工作流。它更像“默认主力模型”，适合复杂分析、多步任务、跨文件修改、方案设计和较重的文档工作。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.4&lt;/code&gt; 则是一个更稳的全能型选择。官方描述是：它把 &lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 的强代码能力带到了更强的推理、工具使用和 agentic workflow 里。换句话说，它不是“弱化版 5.5”，而是一个更均衡、更容易长期当主力的模型。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 仍然是很强的代码模型，但它的核心优势更集中在真实软件工程和 Codex 原生工作流里。官方文档还专门说明：它是面向 agentic coding tasks 优化的模型，而且 &lt;code&gt;GPT-5.4&lt;/code&gt; 的编码能力本身就已经继承了它的长处。&lt;/p&gt;
&lt;p&gt;所以今天再选模型，不太适合把 &lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 直接理解成“最强编程模型”。在大部分日常开发场景里，更推荐先看 &lt;code&gt;GPT-5.5&lt;/code&gt; 和 &lt;code&gt;GPT-5.4&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;按使用场景怎么选&#34;&gt;按使用场景怎么选
&lt;/h2&gt;&lt;p&gt;如果你的任务是日常问答、复杂解释、资料整理、文件分析、长文信息综合，&lt;code&gt;GPT-5.5&lt;/code&gt; 最合适。它不仅适合写代码，也更适合处理“代码之外但又很费脑子”的知识工作。&lt;/p&gt;
&lt;p&gt;如果你的任务是复杂编程、重构、排错、架构设计、多文件修改，仍然优先 &lt;code&gt;GPT-5.5&lt;/code&gt;。Codex 官方推荐也是这样写的：在能用 &lt;code&gt;gpt-5.5&lt;/code&gt; 的地方，大多数任务先从它开始。&lt;/p&gt;
&lt;p&gt;如果你更在意额度和消耗，希望在质量很高的前提下把成本压下来，&lt;code&gt;GPT-5.4&lt;/code&gt; 往往是更合理的默认值。对很多常规开发、普通改写、一般翻译、脚本生成和 bug 修复任务来说，&lt;code&gt;GPT-5.4&lt;/code&gt; 已经足够强，而且更省额度。&lt;/p&gt;
&lt;p&gt;如果你是在 Codex CLI、IDE 扩展或 App 里做更像“工程代理”的事情，比如长时间读仓库、持续改代码、排队跑任务、做 Cloud Tasks 或 Code Review，&lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 仍然有存在感。原因不是它比 &lt;code&gt;GPT-5.5&lt;/code&gt; 更先进，而是当前 Codex 的 Cloud Tasks 和 Code Review 仍然运行在 &lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 上，这决定了它在工程流里还没有退场。&lt;/p&gt;
&lt;h2 id=&#34;消耗额度差多少&#34;&gt;消耗额度差多少
&lt;/h2&gt;&lt;p&gt;在 Codex 的 credits 计费表里，这三个模型的差异非常清楚。&lt;/p&gt;
&lt;p&gt;按 Business / New Enterprise 的 token 计费口径看：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;GPT-5.5&lt;/code&gt;：输入 &lt;code&gt;125 credits / 1M tokens&lt;/code&gt;，缓存输入 &lt;code&gt;12.5 credits&lt;/code&gt;，输出 &lt;code&gt;750 credits&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GPT-5.4&lt;/code&gt;：输入 &lt;code&gt;62.5 credits / 1M tokens&lt;/code&gt;，缓存输入 &lt;code&gt;6.25 credits&lt;/code&gt;，输出 &lt;code&gt;375 credits&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt;：输入 &lt;code&gt;43.75 credits / 1M tokens&lt;/code&gt;，缓存输入 &lt;code&gt;4.375 credits&lt;/code&gt;，输出 &lt;code&gt;350 credits&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这意味着，按名义费率看，&lt;code&gt;GPT-5.4&lt;/code&gt; 大约是 &lt;code&gt;GPT-5.5&lt;/code&gt; 的一半，做同样长度的输入输出时，通常能省接近 &lt;code&gt;50%&lt;/code&gt; 的额度。&lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 的输入更便宜，但输出已经和 &lt;code&gt;GPT-5.4&lt;/code&gt; 很接近，所以它并不是那种“明显更便宜很多”的选择。&lt;/p&gt;
&lt;p&gt;还有一个容易忽略的点：Codex 官方又特别写了一句，&lt;code&gt;GPT-5.5 uses significantly fewer tokens to achieve results comparable to GPT-5.4&lt;/code&gt;。也就是说，虽然它的单价更高，但在某些复杂任务里，可能会靠更少的 token 和更少返工把差距拉回来。&lt;/p&gt;
&lt;p&gt;不过对固定模板文章改写、翻译、SEO 描述生成这种输入输出长度都比较稳定的任务来说，这种“少走弯路”的优势通常没有复杂工程任务那么明显。实际消耗上，&lt;code&gt;GPT-5.4&lt;/code&gt; 大多还是更省，通常可以理解为省掉大约 &lt;code&gt;45%&lt;/code&gt; 到 &lt;code&gt;50%&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;codex-使用限制上的区别&#34;&gt;Codex 使用限制上的区别
&lt;/h2&gt;&lt;p&gt;除了单价，Codex 里的可用方式也不一样。&lt;/p&gt;
&lt;p&gt;截至 &lt;code&gt;2026-05-10&lt;/code&gt;，&lt;code&gt;GPT-5.5&lt;/code&gt; 在 Codex 里是推荐模型，但目前只在使用 ChatGPT 登录的 Codex 中提供，不支持 API key 鉴权。&lt;code&gt;GPT-5.4&lt;/code&gt; 和 &lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 则支持 API 访问。&lt;/p&gt;
&lt;p&gt;另外，&lt;code&gt;GPT-5.5&lt;/code&gt; 和 &lt;code&gt;GPT-5.4&lt;/code&gt; 目前都不支持 Codex Cloud Tasks 和 Code Review；这两项仍然是 &lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 的主场。也就是说，如果你说的是“在 Codex 里长时间跑工程任务”，那就不能只看模型本身强不强，还要看对应功能是不是只有 &lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 才能跑。&lt;/p&gt;
&lt;p&gt;如果你只是本地消息使用，Plus 计划下官方给出的 5 小时窗口大致是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;GPT-5.5&lt;/code&gt;：&lt;code&gt;15-80&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GPT-5.4&lt;/code&gt;：&lt;code&gt;20-100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt;：&lt;code&gt;30-150&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;从这里也能看出一个现实差异：&lt;code&gt;GPT-5.5&lt;/code&gt; 最强，但在固定额度下可用次数通常更少；&lt;code&gt;GPT-5.4&lt;/code&gt; 更均衡；&lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 在本地消息上反而看起来更耐用一些。&lt;/p&gt;
&lt;h2 id=&#34;常用场景怎么选&#34;&gt;常用场景怎么选
&lt;/h2&gt;&lt;p&gt;日常使用里有不少高频任务。更实用的看法，不是抽象地说“哪个更强”，而是按场景一个一个拆开看。&lt;/p&gt;
&lt;h3 id=&#34;1-日常问答资料整理长文总结&#34;&gt;1. 日常问答、资料整理、长文总结
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;GPT-5.5&lt;/code&gt;：最适合。它更擅长处理模糊问题、补齐上下文、把零散信息整理成结构化结果。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.4&lt;/code&gt;：适合普通总结和批量整理。难度不高、数量很多时，通常更划算。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt;：不太适合当主力。能做，但这不是它最有优势的场景。&lt;/p&gt;
&lt;h3 id=&#34;2-技术概念解释代码讲解读旧项目&#34;&gt;2. 技术概念解释、代码讲解、读旧项目
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;GPT-5.5&lt;/code&gt;：适合复杂项目。跨文件关系多、调用链长、历史包袱重时更稳。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.4&lt;/code&gt;：适合常规阅读理解。看函数、看模块、解释配置、帮你快速接手项目都很好用。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt;：更偏工程执行，不是最优先的“讲解型模型”。&lt;/p&gt;
&lt;h3 id=&#34;3-写脚本小工具sqlshell正则&#34;&gt;3. 写脚本、小工具、SQL、Shell、正则
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;GPT-5.5&lt;/code&gt;：适合脚本背后还有系统设计、联动多个服务、涉及复杂约束的情况。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.4&lt;/code&gt;：最适合当默认主力。大多数脚本、小工具、SQL 和命令行任务都够用，而且更省额度。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt;：如果脚本只是整个工程代理链条的一部分，可以考虑；单独写小脚本时不必优先选它。&lt;/p&gt;
&lt;h3 id=&#34;4-改-bug改小功能补测试普通开发&#34;&gt;4. 改 bug、改小功能、补测试、普通开发
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;GPT-5.5&lt;/code&gt;：适合稍复杂的修复，比如需要先分析原因、再跨文件修改、最后补测试。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.4&lt;/code&gt;：最适合日常开发主力。普通 bug、小功能、测试样板、重命名、格式整理这类任务，性价比最好。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt;：能做，但如果没有 Cloud Tasks 或工程代理需求，通常不是第一选择。&lt;/p&gt;
&lt;h3 id=&#34;5-复杂重构架构设计疑难排错&#34;&gt;5. 复杂重构、架构设计、疑难排错
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;GPT-5.5&lt;/code&gt;：最适合。复杂任务里最贵的是返工，不是单次输出；&lt;code&gt;GPT-5.5&lt;/code&gt; 更适合做主解题模型。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.4&lt;/code&gt;：适合中等复杂度任务。可以做方案和重构，但在特别长的上下文、多步推理和高不确定性问题上通常不如 &lt;code&gt;GPT-5.5&lt;/code&gt; 稳。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt;：偏执行，不是这类高难决策任务的默认优先级。&lt;/p&gt;
&lt;h3 id=&#34;6-批量轻任务重复任务拆子任务&#34;&gt;6. 批量轻任务、重复任务、拆子任务
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;GPT-5.5&lt;/code&gt;：能做，但通常不划算。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.4&lt;/code&gt;：最适合。批量改注释、批量改格式、批量生成样板代码、批量改内容时，最平衡。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt;：如果任务已经放进 Codex 的工程流程里，可以考虑；单看性价比，仍然通常不如 &lt;code&gt;GPT-5.4&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id=&#34;7-自动化流水线代理执行持续读写仓库&#34;&gt;7. 自动化流水线、代理执行、持续读写仓库
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;GPT-5.5&lt;/code&gt;：适合做前期方案设计、规则制定、复杂任务拆分。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.4&lt;/code&gt;：适合写自动化脚本、补中等复杂度流程逻辑，尤其是在 API 可接入的情况下。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt;：最值得关注。因为 Codex 的 Cloud Tasks 和 Code Review 还运行在它上面，所以它更适合“让系统自己跑”的工程场景。&lt;/p&gt;
&lt;h3 id=&#34;8-重要页面文案品牌介绍最终润色&#34;&gt;8. 重要页面文案、品牌介绍、最终润色
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;GPT-5.5&lt;/code&gt;：最适合。自然度、风格控制、上下文一致性最好。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.4&lt;/code&gt;：适合大多数普通页面和日常更新，重要页面可以先写初稿再交给 &lt;code&gt;GPT-5.5&lt;/code&gt; 精修。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt;：不适合当主要文案模型。&lt;/p&gt;
&lt;h3 id=&#34;9-网站固定模板文章改写翻译seo-描述&#34;&gt;9. 网站固定模板文章改写、翻译、SEO 描述
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;GPT-5.5&lt;/code&gt;：适合做模板设计、最终润色、重要页面定稿，以及把中文翻成更自然的英文。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.4&lt;/code&gt;：最适合批量生产。普通文章改写、固定结构翻译、商品文案重写、Meta 描述批量生成，通常质量和成本最平衡。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt;：不适合当主要文案模型，更适合写批处理脚本、清洗 HTML、保留标签结构、改自动发布流程。&lt;/p&gt;
&lt;h3 id=&#34;10-电商商品文案分类页批量内容运营&#34;&gt;10. 电商商品文案、分类页、批量内容运营
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;GPT-5.5&lt;/code&gt;：适合定规则、做抽检、做高价值页面的最终润色。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.4&lt;/code&gt;：最适合批量生产。商品标题、分类页说明、批量活动文案、长尾 SEO 内容这类任务上，质量和成本更平衡。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt;：适合写抓取、清洗、批处理、自动发布脚本，不适合负责主要文案。&lt;/p&gt;
&lt;p&gt;如果把这些场景进一步压缩成一句话：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;复杂脑力活、复杂分析、复杂文案：优先 &lt;code&gt;GPT-5.5&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;日常开发、批量生产、重复任务：优先 &lt;code&gt;GPT-5.4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Codex 工程代理、Cloud Tasks、Code Review：重点看 &lt;code&gt;GPT-5.3-Codex&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;最后怎么取舍&#34;&gt;最后怎么取舍
&lt;/h2&gt;&lt;p&gt;如果你只是平时写代码、改 bug、问技术问题、顺手做一些文档工作，&lt;code&gt;GPT-5.4&lt;/code&gt; 是很稳的主力选择。&lt;/p&gt;
&lt;p&gt;如果你要做的是更复杂的项目分析、多文件修改、架构方案、深度排错，或者希望一个模型同时覆盖编程和复杂知识工作，直接优先 &lt;code&gt;GPT-5.5&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;如果你在 Codex 环境里看重的是工程工作流本身，比如 Cloud Tasks、Code Review、长时间代理执行，那么 &lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 仍然值得保留，但它已经不太适合被当成“默认第一选择”。&lt;/p&gt;
&lt;p&gt;对固定模板文章站来说，更实用的搭配通常是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;GPT-5.4&lt;/code&gt; 负责批量生产&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GPT-5.5&lt;/code&gt; 负责定模板、做抽检、做最终润色&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 负责写自动化工具，而不是负责主要文案&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;现在更合理的默认顺序是：&lt;code&gt;GPT-5.5&lt;/code&gt; 第一，&lt;code&gt;GPT-5.4&lt;/code&gt; 第二，&lt;code&gt;GPT-5.3-Codex&lt;/code&gt; 放到更偏工程代理和 Codex 特定能力的场景里使用。&lt;/p&gt;
&lt;p&gt;如果你问的是“同样一篇模板文章改写，&lt;code&gt;GPT-5.4&lt;/code&gt; 比 &lt;code&gt;GPT-5.5&lt;/code&gt; 能省多少”，按官方 credits 表和这类任务的典型 token 结构看，通常可以按“省接近一半”来理解。对批量站内容来说，这个差距已经足够大，所以最常见的做法不是全程上 &lt;code&gt;GPT-5.5&lt;/code&gt;，而是先用 &lt;code&gt;GPT-5.5&lt;/code&gt; 把规则和风格定好，再把大批量任务交给 &lt;code&gt;GPT-5.4&lt;/code&gt;。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>AI Coding 套餐怎么选：轻度看顺手，重度看灵活性</title>
        <link>https://knightli.com/2026/05/10/ai-coding-plan-selection/</link>
        <pubDate>Sun, 10 May 2026 08:20:58 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/10/ai-coding-plan-selection/</guid>
        <description>&lt;p&gt;AI Coding 套餐这半年变化很快。很多工具从“按次”转向“按量”，免费或低价套餐的额度被收紧，部分海外服务还增加了身份验证、地区限制和更严格的用量规则。&lt;/p&gt;
&lt;p&gt;对开发者来说，问题已经不只是“哪个模型最强”，而是：每个月要花多少钱、额度是否够用、工具是否顺手，以及当某个套餐突然涨价或改规则时，能不能平滑切换。&lt;/p&gt;
&lt;p&gt;一个比较实用的结论是：轻度用户买顺手的工具，中度用户买性价比，重度用户买灵活性。使用越重，越不要把模型和工具绑死在同一个套餐里。&lt;/p&gt;
&lt;h2 id=&#34;选套餐先看四件事&#34;&gt;选套餐先看四件事
&lt;/h2&gt;&lt;p&gt;过去选 AI Coding 套餐，通常看三点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;模型能力是否足够强。&lt;/li&gt;
&lt;li&gt;响应速度是否稳定。&lt;/li&gt;
&lt;li&gt;套餐额度是否够用。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;现在还要加上第四点：模型和工具能不能分开。&lt;/p&gt;
&lt;p&gt;模型负责推理能力，工具负责上下文管理、文件编辑、Agent 编排和工作流体验。两者都重要，但最好不要完全绑定。比如喜欢 Claude 模型，可以买官方套餐，也可以通过 API 接到其他工具里；喜欢某个编辑器或 Agent 工具，也最好确认它能接入不同模型，而不是只能使用自家套餐。&lt;/p&gt;
&lt;p&gt;这样做的好处不是折腾，而是降低风险。AI Coding 是变化最快的赛道之一，今天额度宽松的套餐，过两个月可能就改计费；今天好用的工具，下一版也可能因为模型接口变化而体验下降。把模型和工具分开，等于给自己留了迁移空间。&lt;/p&gt;
&lt;h2 id=&#34;海外套餐正在收紧&#34;&gt;海外套餐正在收紧
&lt;/h2&gt;&lt;p&gt;GitHub Copilot、Cursor、Windsurf、Claude Code 这类工具仍然是很多人的主力选择，但整体趋势已经很明确：低价高额度越来越难维持，按量计费越来越常见。&lt;/p&gt;
&lt;p&gt;GitHub Copilot 这类服务开始更强调使用量计费后，套餐本身的“套利空间”会明显减少。对轻度用户来说，它仍然方便；但对高频使用 Agent、长上下文和复杂代码任务的人来说，实际消耗会更接近真实 API 成本。&lt;/p&gt;
&lt;p&gt;Cursor 和 Windsurf 本质上是把模型能力包进 IDE 体验里。它们的优势是开箱即用、编辑器体验成熟，缺点是工具绑定较深。一旦你依赖其中的专属 Agent、索引和自动化流程，后续迁移成本会越来越高。&lt;/p&gt;
&lt;p&gt;Claude Code 的体验和生态热度很高，但海外订阅、身份验证、地区限制、中转服务安全性，都会成为国内用户需要额外评估的风险。尤其是第三方中转服务，可能存在模型掺杂、稳定性不足、数据安全和跑路风险，不适合作为重要项目的长期基础设施。&lt;/p&gt;
&lt;h2 id=&#34;国产套餐的优点和短板&#34;&gt;国产套餐的优点和短板
&lt;/h2&gt;&lt;p&gt;国产 AI Coding 套餐的一个优点，是很多服务以 API 形式提供，天然不太锁定工具。你可以把模型接入 OpenCode、Cline、Continue、自己的脚本或内部 Agent。&lt;/p&gt;
&lt;p&gt;短板也很明显：如果同时要求模型强、速度快、额度足，很少有一个套餐能全部满足。&lt;/p&gt;
&lt;p&gt;GLM 系列在国产模型里能力较强，但高峰期吞吐可能不稳定，重度任务容易被速度卡住。Kimi 的能力不错，但价格和额度规则需要持续关注，尤其要看后台额度是否透明。MiniMax 这类模型速度和额度较友好，适合日常轻任务、批处理和不太复杂的代码辅助，但在复杂工程推理上可能略低一档。DeepSeek 新模型如果处在活动价或优惠期，性价比会很高；活动结束后，就要重新按官方价格和套餐规则评估。&lt;/p&gt;
&lt;p&gt;所以国产方案更适合作为“模型池”使用：不同任务用不同模型，而不是押注一个模型包打天下。&lt;/p&gt;
&lt;h2 id=&#34;轻度用户选顺手的不必折腾-api&#34;&gt;轻度用户：选顺手的，不必折腾 API
&lt;/h2&gt;&lt;p&gt;如果一周只是让 AI 改脚本、补文档、解释报错、写一点小工具，不需要复杂配置。&lt;/p&gt;
&lt;p&gt;这类用户优先选顺手的产品。Cursor、Windsurf、Trae、CodeBuddy、通义灵码、GitHub Copilot 之类都可以尝试。重点不是追求最低单价，而是减少使用门槛：能在你常用编辑器里稳定工作、补全质量不错、出错时容易回退，就足够了。&lt;/p&gt;
&lt;p&gt;轻度用户不建议为了省一点钱去折腾多层 API、中转站和复杂代理。时间成本、账户风险和排错成本往往高于节省下来的订阅费。&lt;/p&gt;
&lt;h2 id=&#34;中度用户看性价比也看可迁移性&#34;&gt;中度用户：看性价比，也看可迁移性
&lt;/h2&gt;&lt;p&gt;如果每天都会用 AI 写代码、改项目、生成测试、整理文档，就要开始关注额度和实际消耗。&lt;/p&gt;
&lt;p&gt;这类用户可以把主力工具和备用模型分开安排。比如一个顺手的 IDE 套餐负责日常编辑，再配一个可接入多工具的 API 或聚合套餐，处理更长上下文、更复杂的 Agent 任务。&lt;/p&gt;
&lt;p&gt;选择时可以重点看三点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;是否支持接入第三方工具。&lt;/li&gt;
&lt;li&gt;是否能清楚看到 token 或额度消耗。&lt;/li&gt;
&lt;li&gt;超额后是限速、降级、停止服务，还是按量付费。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果一个套餐看起来便宜，但只允许在自家工具里使用，就要把迁移成本算进去。如果一个套餐贵一点，但能接入多种工具，反而可能更适合作为长期主力。&lt;/p&gt;
&lt;h2 id=&#34;重度用户不要把模型和工具绑死&#34;&gt;重度用户：不要把模型和工具绑死
&lt;/h2&gt;&lt;p&gt;重度用户的核心诉求是灵活性。&lt;/p&gt;
&lt;p&gt;当一个人或团队每天大量使用 AI Agent，消耗会非常快。复杂代码库检索、长上下文修改、多轮调试、自动化测试修复，都会让 token 消耗成倍增长。此时再依赖单一套餐，很容易遇到三个问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;额度突然不够。&lt;/li&gt;
&lt;li&gt;计费规则突然改变。&lt;/li&gt;
&lt;li&gt;某个工具或模型临时不可用。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;更稳妥的做法是准备多层组合：一个主力 Agent 工具，一个或多个可替换模型接口，一个低成本模型处理简单任务，一个高能力模型处理复杂任务。日常小任务不要都交给最贵模型，关键任务也不要只依赖最便宜模型。&lt;/p&gt;
&lt;p&gt;对重度用户来说，“工具能接任意模型，模型能接入任意工具”比单月便宜几十美元更重要。因为真正贵的不是订阅费，而是工作流被某个生态锁死后，迁移和重建习惯的成本。&lt;/p&gt;
&lt;h2 id=&#34;一个更稳的组合思路&#34;&gt;一个更稳的组合思路
&lt;/h2&gt;&lt;p&gt;比较稳妥的组合可以这样安排：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;轻任务用低成本模型：解释代码、写小脚本、改格式、生成简单文档。&lt;/li&gt;
&lt;li&gt;中等任务用性价比模型：常规功能开发、测试补全、重构建议。&lt;/li&gt;
&lt;li&gt;难任务用强模型：复杂架构调整、跨文件修复、疑难 bug、长上下文推理。&lt;/li&gt;
&lt;li&gt;工具层保持开放：尽量选择能接 API、能导出配置、能切换模型的工具。&lt;/li&gt;
&lt;li&gt;保留备用方案：主力套餐改规则时，可以快速切到另一个模型或工具。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这样不一定最省钱，但更抗波动。AI Coding 套餐的价格和额度还会继续变化，真正值得长期投入的是可迁移的工作流，而不是某个短期看起来特别划算的套餐。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;AI Coding 套餐不适合只看单月价格。轻度用户应该少折腾，选一个顺手的工具；中度用户要开始看额度、消耗和可迁移性；重度用户则要把模型和工具解耦，避免被单一生态绑定。&lt;/p&gt;
&lt;p&gt;现在最值得记住的一点是：套餐会变，模型会变，工具也会变。把选择权留在自己手里，才是长期使用 AI Coding 工具时最重要的成本控制。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>从 PPT 到原型设计：归藏 PPT Skill 与 Huashu Design 使用场景解析</title>
        <link>https://knightli.com/2026/05/09/guizang-ppt-skill-huashu-design-agent-skills/</link>
        <pubDate>Sat, 09 May 2026 08:34:23 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/09/guizang-ppt-skill-huashu-design-agent-skills/</guid>
        <description>&lt;p&gt;最近两个中文开发者做的设计类 Agent Skill 很值得放在一起看：一个是歸藏的 &lt;a class=&#34;link&#34; href=&#34;https://github.com/op7418/guizang-ppt-skill&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;guizang-ppt-skill&lt;/a&gt;，另一个是花叔的 &lt;a class=&#34;link&#34; href=&#34;https://github.com/alchaincyf/huashu-design&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;huashu-design&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;它们都不是传统意义上的“设计工具”，而是把一套设计流程、审美偏好、检查清单和工程模板写成 Agent 可以执行的 Skill。你不是打开一个 UI 慢慢拖元素，而是把需求交给 Claude Code、Codex、Cursor 这类 Agent，让它按固定流程生成 HTML、PPT、动画或原型。&lt;/p&gt;
&lt;p&gt;这类项目的价值，不在于让 AI 随机发挥，而在于把“怎么做才不难看”这件事流程化。&lt;/p&gt;
&lt;h2 id=&#34;guizang-ppt-skill专注杂志风网页-ppt&#34;&gt;guizang-ppt-skill：专注杂志风网页 PPT
&lt;/h2&gt;&lt;p&gt;歸藏的 &lt;code&gt;guizang-ppt-skill&lt;/code&gt; 定位很清楚：生成单文件 HTML 横向翻页 PPT，视觉基调是“电子杂志 × 电子墨水”。它更像一套为演讲准备的版式系统，而不是通用设计框架。&lt;/p&gt;
&lt;p&gt;仓库 README 里列出的核心能力包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;单文件 HTML 输出，不需要构建和服务器，浏览器直接打开。&lt;/li&gt;
&lt;li&gt;横向左右翻页，支持键盘、滚轮、触屏滑动、底部圆点和 ESC 索引。&lt;/li&gt;
&lt;li&gt;5 套主题色预设，包括墨水经典、靛蓝瓷、森林墨、牛皮纸和沙丘。&lt;/li&gt;
&lt;li&gt;10 种页面布局，包括开场封面、章节幕封、数据大字报、左文右图、图片网格、Pipeline、悬念问题、大引用、Before/After 对比和图文混排。&lt;/li&gt;
&lt;li&gt;内置模板、组件说明、布局骨架、主题配置和质量检查清单。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它适合做线下分享、行业内部讲话、私享会、AI 产品发布、demo day，以及带有强烈个人风格的演讲稿。不太适合大段表格数据、培训课件和多人协作编辑。&lt;/p&gt;
&lt;p&gt;这个项目有一个很好的取舍：它没有试图覆盖所有设计场景，而是把“杂志风 PPT”这个场景做窄。主题色只能从预设里选，布局也有明确骨架，这反而降低了 Agent 跑偏的概率。&lt;/p&gt;
&lt;p&gt;如果你经常要把观点、行业观察、产品发布内容做成演讲 deck，它的实用性会很高。&lt;/p&gt;
&lt;p&gt;安装命令也很直接：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npx skills add https://github.com/op7418/guizang-ppt-skill --skill guizang-ppt-skill
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;huashu-design更完整的-html-原生设计工作流&#34;&gt;huashu-design：更完整的 HTML 原生设计工作流
&lt;/h2&gt;&lt;p&gt;花叔的 &lt;code&gt;huashu-design&lt;/code&gt; 覆盖面更大。它的目标不是只做 PPT，而是把 HTML 当成原生设计画布，用 Agent 生成可交付的设计资产。&lt;/p&gt;
&lt;p&gt;仓库 README 里列出的能力包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可点击 App 或 Web 原型。&lt;/li&gt;
&lt;li&gt;HTML 幻灯片，以及可编辑 PPTX 导出。&lt;/li&gt;
&lt;li&gt;产品发布动画、MP4、GIF 和配乐版本。&lt;/li&gt;
&lt;li&gt;多方向设计方案并排对比。&lt;/li&gt;
&lt;li&gt;信息图、数据可视化、PDF、PNG、SVG 导出。&lt;/li&gt;
&lt;li&gt;5 维专家评审，包括哲学一致性、视觉层级、执行工艺、功能性和创新性。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它的核心思路是：让 Agent 先理解品牌和素材，再产出高保真设计。项目里强调了 Core Asset Protocol，也就是遇到具体品牌时，要先确认 logo、产品图、UI 截图、配色、字体和品牌指南，而不是凭记忆猜。&lt;/p&gt;
&lt;p&gt;这点很重要。很多 AI 生成设计看起来“像设计”，但不像某个真实产品或品牌。&lt;code&gt;huashu-design&lt;/code&gt; 试图把这个问题前置解决：先找真实资产，再做设计。&lt;/p&gt;
&lt;p&gt;安装命令是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npx skills add alchaincyf/huashu-design
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;它更适合那些希望在终端里完成较完整设计交付的人：产品原型、发布动画、演示文稿、信息图、设计评审都可以放在一个 Agent 工作流里处理。&lt;/p&gt;
&lt;h2 id=&#34;两者最大的区别&#34;&gt;两者最大的区别
&lt;/h2&gt;&lt;p&gt;简单说，&lt;code&gt;guizang-ppt-skill&lt;/code&gt; 是一个更窄、更稳的演讲 deck 生成器；&lt;code&gt;huashu-design&lt;/code&gt; 是一个更宽、更完整的 HTML 原生设计系统。&lt;/p&gt;
&lt;p&gt;如果只看 PPT：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;guizang-ppt-skill&lt;/code&gt; 更强调杂志感、节奏、版式和单文件浏览器演示。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;huashu-design&lt;/code&gt; 更强调通用设计能力、可编辑 PPTX、品牌素材、导出链路和评审流程。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果看整体设计能力：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;guizang-ppt-skill&lt;/code&gt; 的边界更清晰，适合快速做一份有风格的横向演讲。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;huashu-design&lt;/code&gt; 的能力更综合，适合把一个产品或品牌设计任务拆成原型、动画、幻灯片和信息图。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这两个项目也代表了两种不同的 Skill 写法。前者像一套高度收敛的模板和审美约束，后者像一个小型设计团队的工作流说明书。&lt;/p&gt;
&lt;h2 id=&#34;为什么这类-skill-重要&#34;&gt;为什么这类 Skill 重要
&lt;/h2&gt;&lt;p&gt;Agent 的一个常见问题是“会做，但不稳定”。同样一句需求，有时输出很好，有时就会滑向紫色渐变、圆角卡片、假图标和一堆看似高级的空话。&lt;/p&gt;
&lt;p&gt;Skill 的意义就是把稳定性补上。它把下面这些东西固化下来：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可复用的模板。&lt;/li&gt;
&lt;li&gt;可执行的检查清单。&lt;/li&gt;
&lt;li&gt;明确的审美偏好。&lt;/li&gt;
&lt;li&gt;常见错误的规避规则。&lt;/li&gt;
&lt;li&gt;输出格式和验证流程。&lt;/li&gt;
&lt;li&gt;什么时候该问问题，什么时候该直接开始做。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这比单纯写一句“请做得高级一点”可靠得多。&lt;/p&gt;
&lt;p&gt;尤其是设计任务，审美并不是一句 prompt 就能稳定复现的。真正有用的是流程：先确认素材，再定方向，再搭结构，再做视觉，再检查输出。把这个流程写成 Skill，Agent 才更像一个可协作的执行者，而不是一次性图片生成器。&lt;/p&gt;
&lt;h2 id=&#34;使用建议&#34;&gt;使用建议
&lt;/h2&gt;&lt;p&gt;如果你只是想把一个主题做成线下演讲或分享 deck，可以优先试 &lt;code&gt;guizang-ppt-skill&lt;/code&gt;。它的输出边界窄，单文件 HTML 也方便分发和预览。&lt;/p&gt;
&lt;p&gt;如果你想让 Agent 承担更完整的设计任务，比如 App 原型、发布动画、品牌化幻灯片、可导出 PPTX 或信息图，可以优先看 &lt;code&gt;huashu-design&lt;/code&gt;。它的链路更长，适合需要多轮迭代和交付物导出的任务。&lt;/p&gt;
&lt;p&gt;如果你已经在写自己的 Codex 或 Claude Code Skill，这两个项目也都值得参考：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;想学“如何把一个窄场景做稳”，看 &lt;code&gt;guizang-ppt-skill&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;想学“如何把复杂工作流拆成可执行协议”，看 &lt;code&gt;huashu-design&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结
&lt;/h2&gt;&lt;p&gt;歸藏和花叔这两个项目的共同点，是都把“设计能力”从一次 prompt 变成了可重复执行的流程。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;guizang-ppt-skill&lt;/code&gt; 的重点是杂志风 HTML PPT，适合高风格化演讲；&lt;code&gt;huashu-design&lt;/code&gt; 的重点是 HTML 原生设计系统，覆盖原型、动画、幻灯片、信息图和评审。它们解决的不是“AI 能不能生成设计”，而是“AI 能不能按一套稳定方法生成可交付的设计”。&lt;/p&gt;
&lt;p&gt;这可能会成为 Agent 工具生态里很重要的一类开源项目：不只是代码模板，而是把人的经验、审美和工作方法打包成 Skill。&lt;/p&gt;
&lt;p&gt;参考链接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/op7418/guizang-ppt-skill&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;op7418/guizang-ppt-skill&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/alchaincyf/huashu-design&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;alchaincyf/huashu-design&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Codex vs Claude Code：两套 Subagent 机制怎么选</title>
        <link>https://knightli.com/2026/05/08/codex-vs-claude-code-subagent-design/</link>
        <pubDate>Fri, 08 May 2026 14:01:38 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/08/codex-vs-claude-code-subagent-design/</guid>
        <description>&lt;p&gt;现在的 AI 编程工具越来越重视 Subagent。原因不是功能跟风，而是单个 Agent 处理真实工程任务时，很快会撞到边界。&lt;/p&gt;
&lt;p&gt;一个 Agent 如果同时负责读代码、查日志、改实现、跑测试、分析报错、总结结果，主上下文会很快变脏。搜索结果、命令输出、测试日志和中间推理混在一起，后续判断就会被噪声干扰。任务也很难并行：探索、实现、验证和审查都塞在一条主线上，系统越做越重。&lt;/p&gt;
&lt;p&gt;Subagent 的本质，是给 Agent 减压。主会话不再把所有事情从头做到尾，而是更像协调者：判断目标、安排任务、接收结果，再把结果合成最终答案。子 Agent 处理某一段局部工作，例如探索、实现、验证或审查，并只把压缩后的结论带回来。&lt;/p&gt;
&lt;p&gt;所以 Subagent 不是“再开一个同款自己”，而是把原来糊成一团的工程工作拆成几个边界更清楚的角色。&lt;/p&gt;
&lt;h2 id=&#34;成熟-subagent-系统的底层共识&#34;&gt;成熟 Subagent 系统的底层共识
&lt;/h2&gt;&lt;p&gt;无论具体产品怎么设计，成熟的 Subagent 系统通常都绕不开四件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上下文隔离。&lt;/li&gt;
&lt;li&gt;角色专用化。&lt;/li&gt;
&lt;li&gt;项目和用户级配置。&lt;/li&gt;
&lt;li&gt;工具与权限边界。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上下文隔离是前提。真实仓库里的中间结果很多：搜索结果可能几十条，测试日志可能几百行，命令输出里还混着大量无关信息。这些内容如果直接塞进主会话，主线很快会变乱。Subagent 的价值之一，就是让局部过程先在局部被消化，主会话只看到真正有决策价值的结论。&lt;/p&gt;
&lt;p&gt;角色专用化也很关键。多 Agent 不是多开几个一样的模型一起干活。探索型任务要擅长搜索、阅读、总结；实现型任务要专注改代码和处理局部细节；验证型任务要跑检查、识别风险，并把结果清楚汇报。它们的任务边界、工具权限和输出形式都应该不同。&lt;/p&gt;
&lt;p&gt;工具和权限边界决定了系统能不能安全落地。子 Agent 不应该默认拥有主会话的全部能力。探索型角色未必需要写文件，验证型角色未必需要改实现，后台任务也不该随意越过工作区边界。权限越清楚，协作越可控。&lt;/p&gt;
&lt;p&gt;在这些共识之上，Codex 和 Claude Code 走出了两种不同路线。&lt;/p&gt;
&lt;h2 id=&#34;codex显式派工主会话始终在场&#34;&gt;Codex：显式派工，主会话始终在场
&lt;/h2&gt;&lt;p&gt;Codex 的 Subagent 设计气质更克制。&lt;/p&gt;
&lt;p&gt;它更像是在说：我给你一套受控、轻量、围绕当前主会话展开的分工机制。什么时候派活、派给谁、什么时候收结果，都由主会话明确决定。控制流始终握在当前任务里。&lt;/p&gt;
&lt;p&gt;这种设计的特点是“显式”：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需要子任务时，主会话明确发起委托。&lt;/li&gt;
&lt;li&gt;子任务角色数量保持克制。&lt;/li&gt;
&lt;li&gt;主会话知道哪个 Agent 在做什么。&lt;/li&gt;
&lt;li&gt;结果回到主线后再统一判断。&lt;/li&gt;
&lt;li&gt;协作边界比较透明。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;公开可见的角色思路也偏简洁：通用角色、探索角色、工作角色这类基础分工已经能覆盖很多工程场景。自定义 Agent 更像配置层上的补充，而不是一套非常重的运行时对象系统。&lt;/p&gt;
&lt;p&gt;Codex 这套方式的好处是可预期。它适合需要手动编排、强调确定性、希望主会话始终掌控节奏的团队。比如你正在做一个代码修改任务，可以先派一个探索角色查清调用链，再派一个工作角色做改动，最后由主会话整合并决定是否继续测试。&lt;/p&gt;
&lt;p&gt;它的缺点也很清楚：如果任务越来越复杂，所有编排压力仍然落在主会话身上。主会话要判断何时拆分、如何拆分、派给谁、怎么合并结果。对轻量协作来说这很舒服，对长期复杂工程流来说，可能不如平台化系统省心。&lt;/p&gt;
&lt;h2 id=&#34;claude-code把-agent-做成正式工位&#34;&gt;Claude Code：把 Agent 做成正式工位
&lt;/h2&gt;&lt;p&gt;Claude Code 的取向更平台化。&lt;/p&gt;
&lt;p&gt;它不是只提供几个临时帮手，而是把 Agent 做成可描述、可选择、可配置、可记忆、可隔离、可后台运行的正式对象。子 Agent 不只是会话里的一个工具，而更像工程系统里的一个工位。&lt;/p&gt;
&lt;p&gt;这套思路会把 Agent 列表、适用场景、描述信息、工具边界等内容放进选择逻辑里，让模型判断本轮应该调用哪个角色。这类“模型驱动的委托”会带来更强的自动化：用户不一定每次都显式指定角色，系统可以根据任务类型自己选择。&lt;/p&gt;
&lt;p&gt;从机制上看，Claude Code 更强调几类能力。&lt;/p&gt;
&lt;p&gt;第一是角色体系。探索、规划、通用处理、验证等角色不是随手加几个名字，而是可以带着用途说明、工具限制、默认模型和运行条件存在。探索型角色可以被限制为只读，规划型角色负责设计方案，验证型角色可以专注检查和汇报。&lt;/p&gt;
&lt;p&gt;第二是继承和覆盖。子 Agent 并不是完全自由的，它默认继承主会话的大边界；但在规则允许范围内，也可以通过局部配置调整权限、模式或行为。正确理解不是“全部继承”或“全部覆盖”，而是主会话定义大边界，Agent 在边界内做局部装配。&lt;/p&gt;
&lt;p&gt;第三是记忆。记忆不只是“记住一点内容”，而是可以有作用域。用户级记忆更像长期偏好，项目级记忆更像仓库背景知识，本地级记忆更像只留在当前环境里的私人状态。这样某些 Agent 不必每次从零理解项目。&lt;/p&gt;
&lt;p&gt;第四是后台和工作区隔离。某些验证任务可以在后台持续跑，主线不用停在原地等待。需要强隔离时，Agent 可以进入独立 worktree，像在主工位旁边分出一张独立桌子：仍然在同一个项目里，但操作空间被明确隔开。&lt;/p&gt;
&lt;p&gt;第五是插件生态。只有当 Agent 被视为正式对象时，才会认真考虑它如何被分发、安装、覆盖、排序和接入生态。插件 Agent 可以进入系统，但高风险字段仍应被收口，例如权限模式、hooks、MCP server 等不应该由插件随意声明。&lt;/p&gt;
&lt;p&gt;这让 Claude Code 更像一套 Agent 运行时，而不是单次会话里的协作工具。&lt;/p&gt;
&lt;h2 id=&#34;两种路线的差异&#34;&gt;两种路线的差异
&lt;/h2&gt;&lt;p&gt;可以把两者理解成两种产品哲学。&lt;/p&gt;
&lt;p&gt;Codex 更像受控分工工具：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主会话显式派工。&lt;/li&gt;
&lt;li&gt;角色集保持轻量。&lt;/li&gt;
&lt;li&gt;控制流清晰。&lt;/li&gt;
&lt;li&gt;子任务围绕当前会话展开。&lt;/li&gt;
&lt;li&gt;适合强调确定性和人工编排的工作方式。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Claude Code 更像工程工位系统：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Agent 被正式建模。&lt;/li&gt;
&lt;li&gt;角色更体系化。&lt;/li&gt;
&lt;li&gt;支持记忆、后台、隔离和插件生态。&lt;/li&gt;
&lt;li&gt;模型可以参与选择角色。&lt;/li&gt;
&lt;li&gt;适合长期项目、复杂工作流和平台化扩展。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这不是谁功能更多谁就更好。真正的差别在于：你希望 Subagent 是“我显式叫来的助手”，还是“系统里长期存在的工位”。&lt;/p&gt;
&lt;h2 id=&#34;怎么选择&#34;&gt;怎么选择
&lt;/h2&gt;&lt;p&gt;如果你更看重显式控制、轻量分工、当前会话内的安全并行，Codex 的思路更顺手。它让你清楚知道任务什么时候被拆出去，谁在处理，结果什么时候回来。对代码审查、小型改动、明确的实现任务和需要人工节奏控制的场景，这种方式很稳。&lt;/p&gt;
&lt;p&gt;如果你更看重体系化角色、长期记忆、后台执行、worktree 隔离、插件扩展和更完整的 Agent 运行时，Claude Code 的路线更合适。它适合把 Agent 当成长期参与项目的成员，而不是临时搬一把的助手。&lt;/p&gt;
&lt;p&gt;可以用两个问题判断：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;你能不能接受模型自己选择该派谁干活？&lt;/li&gt;
&lt;li&gt;你是否需要一套更完整的 Agent 运行时？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果第一个问题让你不舒服，说明你更适合显式派工。&lt;br&gt;
如果第二个问题答案是肯定的，说明你可能需要平台化的 Agent 工位系统。&lt;/p&gt;
&lt;h2 id=&#34;使用建议&#34;&gt;使用建议
&lt;/h2&gt;&lt;p&gt;无论选哪种，都不要把 Subagent 当作“多开几个模型就更强”。&lt;/p&gt;
&lt;p&gt;更有效的做法是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;给每个角色明确任务边界。&lt;/li&gt;
&lt;li&gt;控制每个角色能用的工具。&lt;/li&gt;
&lt;li&gt;让子 Agent 输出结论，而不是搬回全部原始日志。&lt;/li&gt;
&lt;li&gt;主会话保留最终决策权。&lt;/li&gt;
&lt;li&gt;对后台任务和工作区隔离保持可见性。&lt;/li&gt;
&lt;li&gt;对插件 Agent 设置明确安全边界。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;工程任务里，Subagent 的价值不在数量，而在分工质量。角色越清楚，上下文越干净，主线判断越稳定。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;Codex 和 Claude Code 都在解决同一个问题：单个 Agent 很难独自承载真实工程任务。它们都承认上下文隔离、角色专用、权限边界和局部汇总的重要性。&lt;/p&gt;
&lt;p&gt;差异在于实现取向。Codex 更克制，强调显式派工和主会话控制；Claude Code 更体系化，把 Agent 做成可配置、可记忆、可隔离、可后台运行、可进入插件生态的正式工位。&lt;/p&gt;
&lt;p&gt;选择哪一个，不是看哪个品牌赢，而是看你的工作方式需要什么：是受控协作工具，还是完整 Agent 运行时。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>9Router：把 Claude Code、Codex、Cursor 接到同一个 AI 路由器</title>
        <link>https://knightli.com/2026/05/08/9router-ai-coding-router-token-saver/</link>
        <pubDate>Fri, 08 May 2026 13:32:38 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/08/9router-ai-coding-router-token-saver/</guid>
        <description>&lt;p&gt;9Router 是一个面向 AI 编程工具的本地路由器。它把 Claude Code、Codex、Cursor、Cline、Copilot、OpenCode、OpenClaw 等工具统一接到一个 OpenAI-compatible endpoint，再由 9Router 负责转发到不同模型和服务商。&lt;/p&gt;
&lt;p&gt;它的目标不是再做一个聊天客户端，而是放在 AI 编程工具和模型服务之间，解决几个实际问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不同工具的 API 格式不一致。&lt;/li&gt;
&lt;li&gt;订阅额度、免费额度和便宜 API 需要手动切换。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git diff&lt;/code&gt;、&lt;code&gt;grep&lt;/code&gt;、&lt;code&gt;ls&lt;/code&gt;、&lt;code&gt;tree&lt;/code&gt; 等工具输出会快速消耗 token。&lt;/li&gt;
&lt;li&gt;某个模型限流或额度耗尽时，编码流程容易中断。&lt;/li&gt;
&lt;li&gt;多账号、多 provider、多模型组合管理成本高。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;根据项目说明，9Router 支持 40+ provider 和 100+ 模型，并提供 RTK Token Saver、自动 fallback、额度追踪、多账号轮询、格式转换和请求日志等功能。项目使用 JavaScript 编写，技术栈包括 Node.js、Next.js、React、Tailwind CSS 和 LowDB，许可证为 MIT。&lt;/p&gt;
&lt;h2 id=&#34;它适合解决什么问题&#34;&gt;它适合解决什么问题
&lt;/h2&gt;&lt;p&gt;9Router 最适合的场景，是你同时使用多个 AI 编程工具和多个模型来源。&lt;/p&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Claude Code 用订阅账号。&lt;/li&gt;
&lt;li&gt;Codex 或 Cursor 需要接自定义 OpenAI endpoint。&lt;/li&gt;
&lt;li&gt;Cline、Continue、RooCode 需要 OpenAI-compatible API。&lt;/li&gt;
&lt;li&gt;免费 provider 作为日常尝试。&lt;/li&gt;
&lt;li&gt;GLM、MiniMax、Kimi 等便宜 API 作为备用。&lt;/li&gt;
&lt;li&gt;某些高质量模型只在复杂任务时使用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;没有 9Router 时，这些配置往往分散在不同工具里。每个工具都要单独写 endpoint、API key、模型名和 fallback 策略。9Router 的思路是让工具都访问同一个本地地址，再在路由器里配置 provider、combo 和优先级。&lt;/p&gt;
&lt;p&gt;默认本地地址是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;http://localhost:20128/v1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Dashboard 地址通常是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;http://localhost:20128/dashboard
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;快速安装&#34;&gt;快速安装
&lt;/h2&gt;&lt;p&gt;如果只是本机使用，可以直接通过 npm 安装：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm install -g 9router
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;9router
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;启动后，Dashboard 会在本地打开。项目文档中的默认端口是 &lt;code&gt;20128&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;如果想从源码运行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone https://github.com/decolua/9router.git
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; 9router
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cp .env.example .env
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm install
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PORT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;20128&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;NEXT_PUBLIC_BASE_URL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;http://localhost:20128 npm run dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;生产模式可以先构建再启动：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm run build
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PORT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;20128&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;HOSTNAME&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;0.0.0.0 &lt;span class=&#34;nv&#34;&gt;NEXT_PUBLIC_BASE_URL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;http://localhost:20128 npm run start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;npm 包当前要求 Node.js &lt;code&gt;&amp;gt;=18.0.0&lt;/code&gt;。如果是部署到 VPS 或 Docker，建议按项目 README 配置 &lt;code&gt;JWT_SECRET&lt;/code&gt;、&lt;code&gt;INITIAL_PASSWORD&lt;/code&gt;、&lt;code&gt;DATA_DIR&lt;/code&gt;、&lt;code&gt;API_KEY_SECRET&lt;/code&gt; 等环境变量，不要直接暴露默认配置。&lt;/p&gt;
&lt;h2 id=&#34;接入-ai-编程工具&#34;&gt;接入 AI 编程工具
&lt;/h2&gt;&lt;p&gt;9Router 对外提供 OpenAI-compatible API，因此大多数支持自定义 OpenAI endpoint 的工具都能接。&lt;/p&gt;
&lt;p&gt;常见配置大致如下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Base URL: http://localhost:20128/v1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;API Key: 从 9Router Dashboard 复制
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Model: 在 9Router 中配置的模型名或 combo 名
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;以 Codex CLI 为例，可以使用环境变量：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;OPENAI_BASE_URL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;http://localhost:20128&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;your-9router-api-key&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex &lt;span class=&#34;s2&#34;&gt;&amp;#34;your prompt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;以 Cline、Continue、RooCode 这类工具为例，通常选择 &lt;code&gt;OpenAI Compatible&lt;/code&gt; provider，然后填入：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Base URL: http://localhost:20128/v1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;API Key: your-9router-api-key
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Model: cc/claude-opus-4-7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;模型名取决于你在 9Router 中连接了哪些 provider。README 中示例包括 &lt;code&gt;cc/&lt;/code&gt;、&lt;code&gt;cx/&lt;/code&gt;、&lt;code&gt;gh/&lt;/code&gt;、&lt;code&gt;glm/&lt;/code&gt;、&lt;code&gt;minimax/&lt;/code&gt;、&lt;code&gt;kr/&lt;/code&gt;、&lt;code&gt;vertex/&lt;/code&gt; 等前缀。&lt;/p&gt;
&lt;h2 id=&#34;rtk-token-saver-的意义&#34;&gt;RTK Token Saver 的意义
&lt;/h2&gt;&lt;p&gt;AI 编程工具消耗 token 最快的地方，往往不是普通对话，而是工具输出。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git diff&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grep&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;find&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ls&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tree&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;日志片段&lt;/li&gt;
&lt;li&gt;大段文件列表&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;9Router 内置 RTK Token Saver，会在请求发给模型前压缩这类工具输出。项目说明称，它可以在很多请求中节省 20%-40% input tokens。&lt;/p&gt;
&lt;p&gt;这个功能的价值在于：它不要求你更换模型，也不改变上层工具使用习惯，而是在路由层减少无效上下文。对经常让 AI 读 diff、搜代码、看目录结构的人来说，这比单纯换一个更便宜的模型更直接。&lt;/p&gt;
&lt;p&gt;不过它不是万能压缩。涉及关键上下文、完整日志或长文件内容时，仍然要留意是否需要保留原始信息。更稳妥的做法是先在本地开发环境里试用，确认回答质量没有明显下降，再把它放到长期工作流里。&lt;/p&gt;
&lt;h2 id=&#34;自动-fallback-怎么用&#34;&gt;自动 fallback 怎么用
&lt;/h2&gt;&lt;p&gt;9Router 的另一个重点是三层 fallback。你可以把模型按优先级组合起来：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1. 订阅模型
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2. 便宜 API
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;3. 免费 provider
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;当第一层额度用完、限流或出错时，9Router 自动切到下一层。这样做的好处是减少手动切换模型的次数，也能避免写代码写到一半突然停住。&lt;/p&gt;
&lt;p&gt;一个常见组合可以是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1. cc/claude-opus-4-7
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2. glm/glm-5.1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;3. kr/claude-sonnet-4.5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果你追求稳定，可以把付费或订阅模型放前面，把便宜模型作为备用；如果你追求低成本，可以把免费 provider 放前面，把便宜 API 放在后面兜底。&lt;/p&gt;
&lt;p&gt;这里要注意：fallback 会影响输出一致性。不同模型的代码风格、推理强度和上下文处理能力不同。对需要严格一致性的任务，比如大型重构、协议实现、数据库迁移，最好固定主模型，只有失败时再手动切换。&lt;/p&gt;
&lt;h2 id=&#34;免费-provider-要谨慎理解&#34;&gt;免费 provider 要谨慎理解
&lt;/h2&gt;&lt;p&gt;项目 README 强调 Kiro、OpenCode Free、Vertex 等免费路径，并且提到部分历史免费层已经变化或不再推荐。&lt;/p&gt;
&lt;p&gt;这类信息变化很快，使用时要按当时 provider 的官方政策确认：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;是否真的免费。&lt;/li&gt;
&lt;li&gt;是否有区域、账号或使用场景限制。&lt;/li&gt;
&lt;li&gt;是否允许接入第三方工具。&lt;/li&gt;
&lt;li&gt;是否可能触发封号或限流。&lt;/li&gt;
&lt;li&gt;免费额度是否有到期时间。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;9Router 可以帮你管理路由和 fallback，但不能改变上游 provider 的服务条款。尤其是把个人订阅、OAuth token 或免费额度接给自动化工具时，最好只在自己可控的本机环境里使用，并定期检查账号安全。&lt;/p&gt;
&lt;h2 id=&#34;本地运行和部署建议&#34;&gt;本地运行和部署建议
&lt;/h2&gt;&lt;p&gt;本机使用时，最简单的方式是只监听 &lt;code&gt;localhost&lt;/code&gt;。这样 Claude Code、Codex、Cursor、Cline 等本地工具可以访问 9Router，但外部网络不能直接连进来。&lt;/p&gt;
&lt;p&gt;如果要部署到 VPS 或局域网服务器，建议至少做到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;修改默认登录密码。&lt;/li&gt;
&lt;li&gt;设置强 &lt;code&gt;JWT_SECRET&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;设置 &lt;code&gt;API_KEY_SECRET&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;开启访问控制或反向代理认证。&lt;/li&gt;
&lt;li&gt;避免把 Dashboard 裸露到公网。&lt;/li&gt;
&lt;li&gt;对 &lt;code&gt;/v1/*&lt;/code&gt; 接口启用 Bearer API key。&lt;/li&gt;
&lt;li&gt;定期备份 &lt;code&gt;DATA_DIR&lt;/code&gt; 下的配置和用量数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Docker 运行时可以参考项目文档，把数据目录挂载出来：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker run -d &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --name 9router &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -p 20128:20128 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --env-file ./.env &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -v 9router-data:/app/data &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -v 9router-usage:/root/.9router &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  9router
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果只是个人开发机使用，没有必要一上来就公网部署。先在本地跑通 provider、combo、工具接入和日志，再决定是否迁移到服务器。&lt;/p&gt;
&lt;h2 id=&#34;适合谁用&#34;&gt;适合谁用
&lt;/h2&gt;&lt;p&gt;9Router 更适合这些用户：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;同时使用多个 AI 编程工具。&lt;/li&gt;
&lt;li&gt;同时有订阅、免费额度和付费 API。&lt;/li&gt;
&lt;li&gt;经常被 provider 限流或额度耗尽打断。&lt;/li&gt;
&lt;li&gt;想把模型 fallback 做成统一配置。&lt;/li&gt;
&lt;li&gt;想减少工具输出带来的 token 浪费。&lt;/li&gt;
&lt;li&gt;愿意自己维护本地代理和 provider 凭据。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你只用一个工具、一个模型，而且额度足够，9Router 可能会增加一层不必要的复杂度。它真正有价值的地方，是把“多工具、多模型、多账号、多价格层”的混乱收进一个本地路由层里。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;9Router 可以理解为 AI 编程工具的本地网关。它把 Claude Code、Codex、Cursor、Cline 等工具统一接到 &lt;code&gt;http://localhost:20128/v1&lt;/code&gt;，再由路由器处理模型选择、格式转换、token 压缩、额度追踪和 fallback。&lt;/p&gt;
&lt;p&gt;它适合重度 AI 编程用户，尤其适合已经在多个 provider 之间来回切换的人。最稳妥的使用方式是先本地安装，接入一个常用工具和一个 provider，确认请求、日志、模型名和 fallback 都正常后，再逐步增加账号和模型组合。&lt;/p&gt;
&lt;p&gt;如果你只是想省心，单一官方客户端仍然更简单。&lt;br&gt;
如果你想把 AI 编程工具变成一套可配置、可切换、可兜底的工作流，9Router 值得试试。&lt;/p&gt;
&lt;h2 id=&#34;参考资料&#34;&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/decolua/9router&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;9Router GitHub 仓库&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://9router.com&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;9Router 官网&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.npmjs.com/package/9router&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;9Router npm 包&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>opencode、Claude Code、Codex 有什么区别？开源 AI 编程工具使用指南</title>
        <link>https://knightli.com/2026/05/08/opencode-open-source-ai-coding-agent/</link>
        <pubDate>Fri, 08 May 2026 08:33:37 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/08/opencode-open-source-ai-coding-agent/</guid>
        <description>&lt;p&gt;&lt;code&gt;opencode&lt;/code&gt; 是 anomalyco 开源的 AI Coding Agent。它的定位很直接：让开发者在终端里使用一个可编程、可扩展、可接入多家模型的代码助手。&lt;/p&gt;
&lt;p&gt;如果把它和 &lt;code&gt;Claude Code&lt;/code&gt;、&lt;code&gt;Codex&lt;/code&gt; 放在一起看，三者解决的是同一类问题：让 AI 进入真实代码库，理解上下文，修改文件，运行命令和测试。但它们的产品取向不一样。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;opencode&lt;/code&gt; 更强调开源、多模型和终端 TUI；&lt;code&gt;Claude Code&lt;/code&gt; 更强调 Anthropic 模型生态和本地工程协作；&lt;code&gt;Codex&lt;/code&gt; 则是 OpenAI 的 AI coding agent，可以在终端、IDE、Codex app 和云端任务里使用。&lt;/p&gt;
&lt;h2 id=&#34;opencode-适合谁&#34;&gt;opencode 适合谁
&lt;/h2&gt;&lt;p&gt;opencode 更适合这几类开发者：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;想在终端里完成代码修改、项目分析和工程任务的人。&lt;/li&gt;
&lt;li&gt;希望 AI Coding Agent 不绑定单一模型提供商的人。&lt;/li&gt;
&lt;li&gt;偏好开源工具，想自己审计、扩展或二次开发的人。&lt;/li&gt;
&lt;li&gt;已经习惯 Neovim、TUI、命令行工作流的人。&lt;/li&gt;
&lt;li&gt;希望以后用桌面端、移动端或其他客户端远程驱动同一个编码代理的人。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它的重点不是做一个聊天窗口，而是把 AI 编程能力放进开发者原本使用的终端和项目目录里。&lt;/p&gt;
&lt;h2 id=&#34;安装方式&#34;&gt;安装方式
&lt;/h2&gt;&lt;p&gt;官方 README 提供了多种安装方式。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 直接安装&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -fsSL https://opencode.ai/install &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# npm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm i -g opencode-ai@latest
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;scoop install opencode
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;choco install opencode
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# macOS 和 Linux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew install anomalyco/tap/opencode
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew install opencode
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Arch Linux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo pacman -S opencode
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;paru -S opencode-bin
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 其他方式&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mise use -g opencode
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nix run nixpkgs#opencode
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;官方也提醒，安装前最好先移除 0.1.x 之前的旧版本，避免旧版本残留造成问题。&lt;/p&gt;
&lt;p&gt;安装脚本会按优先级选择安装目录：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;$OPENCODE_INSTALL_DIR&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$XDG_BIN_DIR&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$HOME/bin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$HOME/.opencode/bin&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果需要指定路径，可以这样写：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;OPENCODE_INSTALL_DIR&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/usr/local/bin curl -fsSL https://opencode.ai/install &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;XDG_BIN_DIR&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;/.local/bin curl -fsSL https://opencode.ai/install &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;桌面应用还在-beta&#34;&gt;桌面应用还在 Beta
&lt;/h2&gt;&lt;p&gt;除了命令行工具，opencode 也提供桌面应用，目前仍处于 Beta。可以从 GitHub Releases 或 &lt;code&gt;opencode.ai/download&lt;/code&gt; 下载。&lt;/p&gt;
&lt;p&gt;桌面端覆盖这些平台：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;平台&lt;/th&gt;
          &lt;th&gt;文件&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;macOS Apple Silicon&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;opencode-desktop-mac-arm64.dmg&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;macOS Intel&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;opencode-desktop-mac-x64.dmg&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Windows&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;opencode-desktop-windows-x64.exe&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Linux&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;.deb&lt;/code&gt;、&lt;code&gt;.rpm&lt;/code&gt; 或 &lt;code&gt;.AppImage&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;macOS 和 Windows 也可以通过包管理器安装桌面端。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew install --cask opencode-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;scoop bucket add extras
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;scoop install extras/opencode-desktop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;两种内置-agent-模式&#34;&gt;两种内置 Agent 模式
&lt;/h2&gt;&lt;p&gt;opencode 内置两种 Agent，可以通过 &lt;code&gt;Tab&lt;/code&gt; 键切换。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;build&lt;/code&gt; 是默认模式，拥有完整开发权限，适合直接修改代码、运行命令和推进工程任务。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;plan&lt;/code&gt; 是只读模式，更适合分析陌生代码库、理解项目结构、制定修改方案。它默认拒绝文件编辑，并且在运行 bash 命令前会询问。&lt;/p&gt;
&lt;p&gt;另外，opencode 还带有一个 &lt;code&gt;general&lt;/code&gt; 子 Agent，用于复杂搜索和多步骤任务。用户可以在消息中输入 &lt;code&gt;@general&lt;/code&gt; 调用。&lt;/p&gt;
&lt;p&gt;这个设计比较实用：真正动手前先用 &lt;code&gt;plan&lt;/code&gt; 看清楚项目，需要改代码时再切到 &lt;code&gt;build&lt;/code&gt;。对于大型仓库，读写权限分开能减少误操作。&lt;/p&gt;
&lt;h2 id=&#34;codex-是什么&#34;&gt;Codex 是什么
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Codex&lt;/code&gt; 是 OpenAI 的 AI coding agent，用来帮助开发者写代码、审查代码、修复 bug 和交付工程任务。&lt;/p&gt;
&lt;p&gt;和单纯的代码补全工具不同，Codex 更接近一个可以操作代码库的 Agent。它可以在本地工具里和你结对，也可以把任务委托到云端执行。OpenAI 官方资料里提到，Codex 可以通过 CLI、IDE、Codex app、ChatGPT/Codex 云端等不同入口使用。&lt;/p&gt;
&lt;p&gt;对开发者来说，Codex 的重点有几处：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以读取代码库、编辑文件、运行命令和测试。&lt;/li&gt;
&lt;li&gt;支持终端、IDE、应用和云端等多种使用界面。&lt;/li&gt;
&lt;li&gt;适合修 bug、写功能、重构、迁移、代码审查和测试补齐。&lt;/li&gt;
&lt;li&gt;更偏 OpenAI 账户、模型和 Codex 产品体系。&lt;/li&gt;
&lt;li&gt;云端任务适合并行处理多个相对清晰的工程任务。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果 opencode 更像一个开放的终端代理框架，Codex 更像 OpenAI 提供的一整套 AI 编程工作台：本地可以结对，云端可以委托，团队可以把它接入更长的工程流程。&lt;/p&gt;
&lt;h2 id=&#34;三者核心区别&#34;&gt;三者核心区别
&lt;/h2&gt;&lt;p&gt;opencode、Claude Code、Codex 都是 AI 编程工具，但选择时可以先看这几个维度。&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;工具&lt;/th&gt;
          &lt;th&gt;核心定位&lt;/th&gt;
          &lt;th&gt;主要优势&lt;/th&gt;
          &lt;th&gt;更适合&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;opencode&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;开源 AI Coding Agent&lt;/td&gt;
          &lt;td&gt;开源、多模型、TUI、客户端/服务器架构&lt;/td&gt;
          &lt;td&gt;想要开放工具链、可替换模型、偏终端工作流的开发者&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;Claude Code&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Anthropic 的命令行编程工具&lt;/td&gt;
          &lt;td&gt;Claude 模型体验、代码理解、长上下文、工程任务协作&lt;/td&gt;
          &lt;td&gt;已经使用 Claude/Anthropic 生态，希望本地推进代码任务的开发者&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;Codex&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;OpenAI 的 AI coding agent&lt;/td&gt;
          &lt;td&gt;CLI、IDE、Codex app、云端任务、多 Agent 工作流&lt;/td&gt;
          &lt;td&gt;已经使用 ChatGPT/OpenAI，希望本地结对和云端委托并用的团队&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;简单说，opencode 的关键词是“开源和可替换”，Claude Code 的关键词是“Claude 生态和本地工程代理”，Codex 的关键词是“OpenAI 生态和多入口协作”。&lt;/p&gt;
&lt;h2 id=&#34;和-claude-code-的区别&#34;&gt;和 Claude Code 的区别
&lt;/h2&gt;&lt;p&gt;opencode 的官方 FAQ 直接把 Claude Code 拿来对比。两者能力上很接近，但差异主要在这几处。&lt;/p&gt;
&lt;p&gt;第一，opencode 是 100% 开源项目，代码托管在 GitHub，并使用 MIT license。&lt;/p&gt;
&lt;p&gt;第二，opencode 不绑定单一模型提供商。它推荐 OpenCode Zen 提供的模型，但也可以搭配 Claude、OpenAI、Google 或本地模型。对开发者来说，这意味着模型成本、能力和可用性变化时，不必被某一个平台锁住。&lt;/p&gt;
&lt;p&gt;第三，opencode 内置可选的 LSP 支持。对代码补全、跳转、诊断和项目理解来说，LSP 是非常关键的基础能力。&lt;/p&gt;
&lt;p&gt;第四，opencode 更强调 TUI。它由 Neovim 用户和 terminal.shop 的创建者打造，产品重心明显放在终端体验上。&lt;/p&gt;
&lt;p&gt;第五，opencode 采用客户端/服务器架构。也就是说，opencode 可以在你的电脑上运行，未来由 TUI、桌面端、移动端或其他客户端来控制。TUI 只是其中一种前端形态。&lt;/p&gt;
&lt;h2 id=&#34;什么时候选-opencodeclaude-code-或-codex&#34;&gt;什么时候选 opencode、Claude Code 或 Codex
&lt;/h2&gt;&lt;p&gt;如果你已经在使用 Claude Code 或 Codex，opencode 不一定是立刻替换它们的工具。更合理的看法是：它提供了一个开源、可替换模型、偏终端的选择。&lt;/p&gt;
&lt;p&gt;可以优先考虑 opencode 的场景包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你希望 AI 编程工具尽量开源。&lt;/li&gt;
&lt;li&gt;你不想把工作流绑定在某个模型供应商上。&lt;/li&gt;
&lt;li&gt;你希望用同一个工具测试 Claude、OpenAI、Google 或本地模型。&lt;/li&gt;
&lt;li&gt;你喜欢 TUI，不希望主要工作流被桌面应用或网页应用打断。&lt;/li&gt;
&lt;li&gt;你关注客户端/服务器架构带来的远程控制能力。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可以优先考虑 Claude Code 的场景包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你主要使用 Claude 模型。&lt;/li&gt;
&lt;li&gt;你重视长上下文、代码理解和复杂工程任务协作。&lt;/li&gt;
&lt;li&gt;你希望在本地仓库中持续推进修改、测试和重构。&lt;/li&gt;
&lt;li&gt;你更信任 Anthropic 对 Claude Code 的默认产品体验。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可以优先考虑 Codex 的场景包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你已经在使用 ChatGPT 或 OpenAI 账户体系。&lt;/li&gt;
&lt;li&gt;你希望同一个 coding agent 覆盖终端、IDE、桌面应用和云端任务。&lt;/li&gt;
&lt;li&gt;你想把较清晰的 bug 修复、功能开发、迁移、测试补齐交给云端并行处理。&lt;/li&gt;
&lt;li&gt;你需要代码审查、后台任务、团队协作和多 Agent 工作流。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你更看重官方闭环体验、模型默认配置、企业管理和现成集成，Claude Code 或 Codex 可能更省心；如果你更看重可控性、开放性和 provider-agnostic，opencode 更值得关注。&lt;/p&gt;
&lt;h2 id=&#34;需要注意的地方&#34;&gt;需要注意的地方
&lt;/h2&gt;&lt;p&gt;opencode、Claude Code 和 Codex 都发展很快，GitHub release、安装命令、桌面端文件名、模型可用性和套餐权限都可能变化。实际安装和选型前，最好直接查看各自官方 README、文档和发布页面。&lt;/p&gt;
&lt;p&gt;另外，它的桌面应用仍然标注为 Beta，不适合默认当作稳定生产工具。对于日常工程任务，终端版仍然是更主要的入口。&lt;/p&gt;
&lt;p&gt;从工具趋势看，opencode 代表的是 AI Coding Agent 的开放工具链方向：模型可以替换，客户端可以替换，核心代理能力尽量开放。Codex 和 Claude Code 则更像模型公司把 coding agent 做成完整产品入口。对开发者来说，这两条路线会长期并存。&lt;/p&gt;
&lt;h2 id=&#34;参考链接&#34;&gt;参考链接
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;opencode GitHub：&lt;a class=&#34;link&#34; href=&#34;https://github.com/anomalyco/opencode&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/anomalyco/opencode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;opencode 官网：&lt;a class=&#34;link&#34; href=&#34;https://opencode.ai&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://opencode.ai&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;opencode 文档：&lt;a class=&#34;link&#34; href=&#34;https://opencode.ai/docs&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://opencode.ai/docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;opencode Releases：&lt;a class=&#34;link&#34; href=&#34;https://github.com/anomalyco/opencode/releases&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/anomalyco/opencode/releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenAI Codex：&lt;a class=&#34;link&#34; href=&#34;https://openai.com/codex/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://openai.com/codex/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Using Codex with your ChatGPT plan：&lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/11369540-codex-in-chatgpt&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://help.openai.com/en/articles/11369540-codex-in-chatgpt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenAI Codex CLI Getting Started：&lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/11096431-openai-codex-ci-getting-started&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://help.openai.com/en/articles/11096431-openai-codex-ci-getting-started&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Awesome Codex Skills：给 Codex CLI 扩展技能的社区清单</title>
        <link>https://knightli.com/2026/05/07/awesome-codex-skills-composio/</link>
        <pubDate>Thu, 07 May 2026 20:19:15 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/07/awesome-codex-skills-composio/</guid>
        <description>&lt;p&gt;ComposioHQ 的 &lt;a class=&#34;link&#34; href=&#34;https://github.com/ComposioHQ/awesome-codex-skills&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;awesome-codex-skills&lt;/a&gt; 是一个面向 Codex CLI 的社区技能清单。它的价值不在于再写一堆提示词模板，而是把一类可重复的工作流程整理成可安装、可复用、可维护的 Skill。&lt;/p&gt;
&lt;p&gt;如果你已经把 Codex 当成日常开发搭档，这类仓库的意义会很直接：把经常重复讲的规则、命令、资料入口和操作步骤沉淀下来，下次只要调用对应技能，Codex 就能按同一套上下文继续工作。&lt;/p&gt;
&lt;h2 id=&#34;这个仓库解决什么问题&#34;&gt;这个仓库解决什么问题
&lt;/h2&gt;&lt;p&gt;Codex Skills 可以理解成给 Codex CLI 增加“专门工作模式”的方式。普通提示词适合临时说明一次需求，Skill 更适合长期复用。&lt;/p&gt;
&lt;p&gt;比如你经常需要：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;按固定格式生成提交信息；&lt;/li&gt;
&lt;li&gt;查阅某类 API 文档；&lt;/li&gt;
&lt;li&gt;运行特定项目的测试和部署命令；&lt;/li&gt;
&lt;li&gt;按团队规范重写文章、翻译文档或整理资料；&lt;/li&gt;
&lt;li&gt;调用外部工具完成重复性的开发辅助任务。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些内容如果每次都重新输入，很快就会变成负担。Skill 的思路是把这些规则放进一个独立目录里，核心通常是一份 &lt;code&gt;SKILL.md&lt;/code&gt;，必要时再配合脚本、模板、参考资料或资产文件。Codex 在被触发时读取这份说明，然后按照里面定义的流程执行。&lt;/p&gt;
&lt;h2 id=&#34;和普通提示词有什么不同&#34;&gt;和普通提示词有什么不同
&lt;/h2&gt;&lt;p&gt;普通提示词更像一次性指令，适合告诉模型“这次怎么做”。Skill 更像一个小型操作手册，适合告诉 Codex“以后遇到这类任务都按这个方式做”。&lt;/p&gt;
&lt;p&gt;它的优势主要有三个：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;可复用&lt;/strong&gt;：常用工作流不用反复复制粘贴。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可审查&lt;/strong&gt;：技能文件通常是本地 Markdown，可以直接打开、修改和版本管理。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可扩展&lt;/strong&gt;：复杂技能可以带脚本、模板和参考资料，不只是自然语言说明。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这也是 &lt;code&gt;awesome-codex-skills&lt;/code&gt; 这类清单的价值所在：它帮你集中发现已经写好的技能，再根据自己的工作习惯挑选、安装和改造。&lt;/p&gt;
&lt;h2 id=&#34;如何安装和使用&#34;&gt;如何安装和使用
&lt;/h2&gt;&lt;p&gt;仓库提供了安装脚本，也支持手动安装。典型流程是先克隆仓库，再运行安装脚本：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone https://github.com/ComposioHQ/awesome-codex-skills.git
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; awesome-codex-skills
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python install.py
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果你只想试用少数技能，建议先看清每个技能目录里的 &lt;code&gt;SKILL.md&lt;/code&gt;，确认它会读取哪些资料、运行哪些脚本、修改哪些文件，再安装到本地 Codex skills 目录。&lt;/p&gt;
&lt;p&gt;安装之后，Codex 可以在合适的任务中自动匹配技能，也可以通过明确点名的方式调用。对长期使用者来说，更实用的方式往往是：先安装一个社区技能，再把里面的说明改成自己的项目规范。&lt;/p&gt;
&lt;h2 id=&#34;适合关注哪些技能&#34;&gt;适合关注哪些技能
&lt;/h2&gt;&lt;p&gt;这类仓库里最值得优先看的，不一定是名字最酷的技能，而是能稳定减少重复劳动的技能。&lt;/p&gt;
&lt;p&gt;我会优先关注几类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;开发流程类&lt;/strong&gt;：代码审查、测试、提交、发布、依赖检查。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文档处理类&lt;/strong&gt;：重写、翻译、摘要、结构化整理。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工具集成类&lt;/strong&gt;：把 Codex 和外部服务、API、命令行工具连接起来。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;项目规范类&lt;/strong&gt;：把团队约定、目录结构、命名规则、部署步骤写进固定流程。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果一个技能只是把一句提示词包装了一下，价值有限；如果它能把“查资料、判断、执行、验证、输出”串成稳定流程，就值得长期保留。&lt;/p&gt;
&lt;h2 id=&#34;使用时要注意什么&#34;&gt;使用时要注意什么
&lt;/h2&gt;&lt;p&gt;社区技能虽然方便，但不要把它当成黑盒直接运行。尤其是带脚本的 Skill，安装前最好先检查三件事：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;SKILL.md&lt;/code&gt; 里要求 Codex 做什么；&lt;/li&gt;
&lt;li&gt;是否包含会访问网络、读写文件或调用外部服务的脚本；&lt;/li&gt;
&lt;li&gt;默认路径、命令和权限是否适合你的本地环境。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Skill 本质上是在扩大 Codex 的行动边界。写得好，它会让 Codex 更像熟悉你项目的同事；写得粗糙，它也可能把不适合你的规则带进工作流。所以最理想的用法不是“装很多”，而是“装少数、改到顺手、长期维护”。&lt;/p&gt;
&lt;h2 id=&#34;我的判断&#34;&gt;我的判断
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;awesome-codex-skills&lt;/code&gt; 值得收藏，尤其适合已经开始用 Codex CLI 做真实开发、文档或自动化任务的人。它不是官方能力本身，而是一个社区整理的技能入口：你可以从里面找灵感，也可以把常用流程改造成自己的本地技能库。&lt;/p&gt;
&lt;p&gt;对重度用户来说，Codex Skills 的重点不是让 AI 多记一点东西，而是让 AI 在同类任务中少走弯路。把规则写成 Skill，等于把一次次临时沟通沉淀成可复用的工作基础设施。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>CC Switch：一个桌面工具统一管理 Claude Code、Codex、Gemini CLI 和 OpenClaw</title>
        <link>https://knightli.com/2026/05/06/cc-switch-ai-cli-manager/</link>
        <pubDate>Wed, 06 May 2026 09:03:08 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/06/cc-switch-ai-cli-manager/</guid>
        <description>&lt;p&gt;&lt;code&gt;CC Switch&lt;/code&gt; 是一个面向 AI 编程重度用户的桌面管理工具。它要解决的问题很直接：现在很多人同时使用 &lt;code&gt;Claude Code&lt;/code&gt;、&lt;code&gt;Codex&lt;/code&gt;、&lt;code&gt;Gemini CLI&lt;/code&gt;、&lt;code&gt;OpenCode&lt;/code&gt;、&lt;code&gt;OpenClaw&lt;/code&gt;，但每个工具都有自己的配置格式、Provider 写法、MCP 配置和 Skills 管理方式。&lt;/p&gt;
&lt;p&gt;当你只用一个工具时，手动改配置还能忍；一旦多个工具混用，再加上官方账号、第三方 API、中转服务、本地模型和团队共享配置，手动编辑 JSON、TOML、&lt;code&gt;.env&lt;/code&gt; 很快就会变成一件很烦的事。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CC Switch&lt;/code&gt; 的定位，就是把这些分散配置收进一个跨平台桌面应用里。&lt;/p&gt;
&lt;h2 id=&#34;它解决什么问题&#34;&gt;它解决什么问题
&lt;/h2&gt;&lt;p&gt;现代 AI 编程工具越来越像“命令行里的开发同事”，但每个工具的生态还没有完全统一。&lt;/p&gt;
&lt;p&gt;常见痛点包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Claude Code、Codex、Gemini CLI、OpenCode、OpenClaw 配置格式不同。&lt;/li&gt;
&lt;li&gt;切换 API Provider 时，要反复改配置文件。&lt;/li&gt;
&lt;li&gt;MCP server 在不同工具之间重复配置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;、&lt;code&gt;AGENTS.md&lt;/code&gt;、&lt;code&gt;GEMINI.md&lt;/code&gt; 这类提示文件难以统一维护。&lt;/li&gt;
&lt;li&gt;Skills 安装、同步、备份和卸载缺少一个集中入口。&lt;/li&gt;
&lt;li&gt;多个账号、多个 relay、多个模型服务切换很容易搞混。&lt;/li&gt;
&lt;li&gt;配置文件手工修改出错后，排查成本很高。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;CC Switch&lt;/code&gt; 的思路是：不要让用户记住每个工具的配置细节，而是用一个统一界面管理 Provider、MCP、Prompts、Skills、Sessions 和代理。&lt;/p&gt;
&lt;h2 id=&#34;支持哪些工具&#34;&gt;支持哪些工具
&lt;/h2&gt;&lt;p&gt;README 中列出的核心支持对象包括五类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Claude Code&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Codex&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Gemini CLI&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OpenCode&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OpenClaw&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这几个工具本身定位相近，都是围绕 AI 编程、Agent 工作流和命令行协作展开。但它们的配置体系不同，&lt;code&gt;CC Switch&lt;/code&gt; 的价值就在于把这些差异包装起来。&lt;/p&gt;
&lt;p&gt;对经常比较不同 AI 编程工具的人来说，这比每次手动翻配置文件省心很多。&lt;/p&gt;
&lt;h2 id=&#34;provider-管理&#34;&gt;Provider 管理
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;CC Switch&lt;/code&gt; 的第一层能力是 Provider 管理。&lt;/p&gt;
&lt;p&gt;它内置了 50 多个 Provider 预设，README 中提到的方向包括 AWS Bedrock、NVIDIA NIM，以及各种社区 relay。用户可以复制 API key，一键导入，然后在界面中切换。&lt;/p&gt;
&lt;p&gt;实用点主要有几个：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一键添加 Provider。&lt;/li&gt;
&lt;li&gt;Provider 拖拽排序。&lt;/li&gt;
&lt;li&gt;系统托盘快速切换。&lt;/li&gt;
&lt;li&gt;Provider 导入和导出。&lt;/li&gt;
&lt;li&gt;部分通用 Provider 可同步到多个应用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对很多人来说，这个功能已经足够有吸引力。因为 AI 编程工具的日常使用，经常不是“模型不会用”，而是“今天这个 key 用哪个工具、哪个 endpoint、哪个账号”容易乱。&lt;/p&gt;
&lt;h2 id=&#34;本地代理与故障切换&#34;&gt;本地代理与故障切换
&lt;/h2&gt;&lt;p&gt;除了写配置文件，&lt;code&gt;CC Switch&lt;/code&gt; 还提供本地代理模式。&lt;/p&gt;
&lt;p&gt;这个能力的重点是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;热切换 Provider。&lt;/li&gt;
&lt;li&gt;格式转换。&lt;/li&gt;
&lt;li&gt;自动故障转移。&lt;/li&gt;
&lt;li&gt;熔断器。&lt;/li&gt;
&lt;li&gt;Provider 健康检查。&lt;/li&gt;
&lt;li&gt;请求修正。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;简单说，它不只是把配置写进目标工具，还可以在中间加一层本地代理，让不同工具通过代理访问模型服务。&lt;/p&gt;
&lt;p&gt;这对多 Provider 用户很有用：一个服务挂了，可以切到另一个；一个模型贵，可以换成更便宜的；某个请求格式不兼容，也可以通过代理层做适配。&lt;/p&gt;
&lt;h2 id=&#34;mcpprompts-和-skills&#34;&gt;MCP、Prompts 和 Skills
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;CC Switch&lt;/code&gt; 比较重要的第二层能力，是统一管理 MCP、Prompts 和 Skills。&lt;/p&gt;
&lt;h3 id=&#34;mcp&#34;&gt;MCP
&lt;/h3&gt;&lt;p&gt;它提供统一 MCP 面板，可以在多个应用之间管理 MCP server，并支持双向同步和 Deep Link 导入。&lt;/p&gt;
&lt;p&gt;这对正在用 MCP 的用户很实用。因为 MCP server 一多，配置很容易分散在不同客户端里。统一面板可以减少重复配置，也方便迁移。&lt;/p&gt;
&lt;h3 id=&#34;prompts&#34;&gt;Prompts
&lt;/h3&gt;&lt;p&gt;Prompts 部分支持 Markdown 编辑，并且可以在不同工具之间同步对应文件，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GEMINI.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些文件本质上都是给 Agent 的项目说明书。统一管理后，可以更容易维护团队规则、项目约定和全局提示。&lt;/p&gt;
&lt;h3 id=&#34;skills&#34;&gt;Skills
&lt;/h3&gt;&lt;p&gt;Skills 支持从 GitHub 仓库或 ZIP 文件一键安装，也支持自定义仓库管理、符号链接和文件复制。&lt;/p&gt;
&lt;p&gt;如果你同时使用 Claude Code、Codex、OpenClaw 这类工具，Skills 很容易变成一堆散落在不同目录的文件。&lt;code&gt;CC Switch&lt;/code&gt; 把它们集中起来，能降低维护成本。&lt;/p&gt;
&lt;h2 id=&#34;会话与工作区&#34;&gt;会话与工作区
&lt;/h2&gt;&lt;p&gt;README 还提到 Session Manager 和 Workspace 相关能力。&lt;/p&gt;
&lt;p&gt;它可以浏览、搜索和恢复多个应用里的会话历史。对长期使用 AI 编程工具的人来说，会话管理其实很重要：很多有价值的上下文、调试过程、方案比较，都埋在旧对话里。&lt;/p&gt;
&lt;p&gt;此外，它还为 OpenClaw 提供 Workspace editor，可以编辑 &lt;code&gt;AGENTS.md&lt;/code&gt;、&lt;code&gt;SOUL.md&lt;/code&gt; 等 agent 文件，并带 Markdown 预览。&lt;/p&gt;
&lt;p&gt;这说明 &lt;code&gt;CC Switch&lt;/code&gt; 不只是一个“切换 key 的小工具”，而是在往 AI Agent 工作台方向扩展。&lt;/p&gt;
&lt;h2 id=&#34;云同步与数据存储&#34;&gt;云同步与数据存储
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;CC Switch&lt;/code&gt; 支持通过 Dropbox、OneDrive、iCloud、NAS 或 WebDAV 同步 Provider 数据。&lt;/p&gt;
&lt;p&gt;本地数据存储方式也比较清楚：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据库：&lt;code&gt;~/.cc-switch/cc-switch.db&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;本地设置：&lt;code&gt;~/.cc-switch/settings.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;自动备份：&lt;code&gt;~/.cc-switch/backups/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Skills：&lt;code&gt;~/.cc-switch/skills/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Skill 备份：&lt;code&gt;~/.cc-switch/skill-backups/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它使用 SQLite 作为主要数据源，并强调原子写入和自动备份，目标是避免配置文件在切换或写入时损坏。&lt;/p&gt;
&lt;p&gt;这个设计对重度用户很关键。因为一旦配置管理工具本身把配置写坏，影响的是所有 AI 编程工具。&lt;/p&gt;
&lt;h2 id=&#34;安装方式&#34;&gt;安装方式
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;CC Switch&lt;/code&gt; 是跨平台桌面应用，基于 Tauri 2 构建。&lt;/p&gt;
&lt;p&gt;系统要求大致如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Windows：Windows 10 及以上&lt;/li&gt;
&lt;li&gt;macOS：macOS 12 Monterey 及以上&lt;/li&gt;
&lt;li&gt;Linux：Ubuntu 22.04+、Debian 11+、Fedora 34+ 等主流发行版&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Windows 用户可以下载 &lt;code&gt;.msi&lt;/code&gt; 安装包或便携版压缩包。&lt;/p&gt;
&lt;p&gt;macOS 用户可以用 Homebrew：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew tap farion1231/ccswitch
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew install --cask cc-switch
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;更新：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew upgrade --cask cc-switch
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Linux 用户可以选择 &lt;code&gt;.deb&lt;/code&gt;、&lt;code&gt;.rpm&lt;/code&gt; 或 AppImage。Arch Linux 用户也可以通过 &lt;code&gt;paru -S cc-switch-bin&lt;/code&gt; 安装。&lt;/p&gt;
&lt;p&gt;截至 2026 年 5 月 6 日，仓库页面显示最新 release 为 &lt;code&gt;CC Switch v3.14.1&lt;/code&gt;，发布时间是 2026 年 4 月 23 日。&lt;/p&gt;
&lt;h2 id=&#34;技术栈&#34;&gt;技术栈
&lt;/h2&gt;&lt;p&gt;从仓库结构看，&lt;code&gt;CC Switch&lt;/code&gt; 是典型的 Tauri 桌面应用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;前端：React 18、TypeScript、Vite、TailwindCSS、TanStack Query、shadcn/ui&lt;/li&gt;
&lt;li&gt;后端：Tauri 2、Rust、SQLite、Tokio&lt;/li&gt;
&lt;li&gt;测试：Vitest、MSW、Testing Library&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;核心设计模式包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SQLite 作为 Single Source of Truth。&lt;/li&gt;
&lt;li&gt;JSON 保存设备级本地设置。&lt;/li&gt;
&lt;li&gt;切换时写入目标工具的 live config。&lt;/li&gt;
&lt;li&gt;编辑当前 Provider 时从 live config 回填。&lt;/li&gt;
&lt;li&gt;使用临时文件加 rename 的方式做原子写入。&lt;/li&gt;
&lt;li&gt;数据库连接加锁，避免并发写入问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这类架构说明项目并不是简单脚本，而是按长期桌面工具来设计的。&lt;/p&gt;
&lt;h2 id=&#34;适合谁用&#34;&gt;适合谁用
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;CC Switch&lt;/code&gt; 适合下面几类用户：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;同时使用 Claude Code、Codex、Gemini CLI、OpenCode、OpenClaw。&lt;/li&gt;
&lt;li&gt;经常切换官方账号、第三方 relay、本地模型或团队 Provider。&lt;/li&gt;
&lt;li&gt;已经开始大量使用 MCP。&lt;/li&gt;
&lt;li&gt;想统一维护 &lt;code&gt;CLAUDE.md&lt;/code&gt;、&lt;code&gt;AGENTS.md&lt;/code&gt;、&lt;code&gt;GEMINI.md&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;经常安装、测试和迁移 Skills。&lt;/li&gt;
&lt;li&gt;想看不同工具的会话历史和使用情况。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你只用一个 AI 编程工具，而且一直走官方登录，不怎么折腾 Provider、MCP 和 Skills，那它的价值可能没那么明显。&lt;/p&gt;
&lt;p&gt;但如果你已经进入“多工具、多账号、多 Provider、多项目”的状态，它能省掉很多琐碎配置工作。&lt;/p&gt;
&lt;h2 id=&#34;需要注意什么&#34;&gt;需要注意什么
&lt;/h2&gt;&lt;p&gt;这类工具很方便，但也要注意边界。&lt;/p&gt;
&lt;p&gt;第一，它会管理多个 AI CLI 的配置，因此要确认自己信任这个工具和它的写入逻辑。&lt;/p&gt;
&lt;p&gt;第二，API key、relay endpoint、MCP server 都属于敏感配置。开启云同步前，要确认同步目录和 WebDAV 服务本身安全可靠。&lt;/p&gt;
&lt;p&gt;第三，切换 Provider 后，多数工具仍然需要重启终端或 CLI 才能生效。README 中提到，Claude Code 对 Provider 数据支持热切换，但其他工具通常仍需要重启。&lt;/p&gt;
&lt;p&gt;第四，切回官方登录时，最好按项目说明添加 official provider，再重新走对应工具的登录流程。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;CC Switch&lt;/code&gt; 的价值不在于又做了一个 AI 编程工具，而在于它承认了一个现实：AI 编程生态已经进入多工具并存阶段。&lt;/p&gt;
&lt;p&gt;Claude Code、Codex、Gemini CLI、OpenCode、OpenClaw 各有自己的配置系统，MCP、Skills、Prompts、Provider 又在快速扩展。继续靠手动改配置，迟早会变成负担。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CC Switch&lt;/code&gt; 把这些东西收进一个桌面应用里，让用户可以更轻松地切换 Provider、同步 MCP、管理 Skills、维护提示文件和查看会话。对重度 AI 编程用户来说，这类工具很可能会从“可选小工具”变成“日常基础设施”。&lt;/p&gt;
&lt;h2 id=&#34;参考资料&#34;&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/farion1231/cc-switch&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;farion1231/cc-switch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Codex App 保姆级上手：安装、沙盒、并行任务、Skills 与 MCP</title>
        <link>https://knightli.com/2026/05/06/codex-app-complete-guide-skills-mcp/</link>
        <pubDate>Wed, 06 May 2026 08:41:17 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/06/codex-app-complete-guide-skills-mcp/</guid>
        <description>&lt;p&gt;Codex App 可以理解成一个面向 AI 编程的任务工作台。它不是传统 IDE，也不是单纯聊天窗口，而是把多任务、项目管理、沙盒权限、Git、云端运行、插件、Skills、MCP 和自动化集中到一个界面里。&lt;/p&gt;
&lt;p&gt;如果你已经在用 Codex CLI、Claude Code、Cursor 或其他 coding agent，Codex App 最值得关注的地方，是它把“多个 agent 并行干活”做成了一个更清晰的桌面工作流。&lt;/p&gt;
&lt;h2 id=&#34;codex-app-适合做什么&#34;&gt;Codex App 适合做什么
&lt;/h2&gt;&lt;p&gt;Codex App 的核心价值不是让 AI 回答问题，而是让 AI 在项目目录里持续执行任务：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;修改代码、运行命令、启动开发服务。&lt;/li&gt;
&lt;li&gt;管理多个项目和多个任务。&lt;/li&gt;
&lt;li&gt;在本地或云端执行长任务。&lt;/li&gt;
&lt;li&gt;调用插件、Skills 和 MCP 扩展能力。&lt;/li&gt;
&lt;li&gt;通过 Git、worktree 和 PR 管理改动。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OpenAI 官方也把 Codex App 定位成一个用于管理多个 coding agent 的界面。它适合需要同时推进多个代码任务的人，尤其适合前端页面、脚本工具、小型应用、文档整理和自动化工作流。&lt;/p&gt;
&lt;h2 id=&#34;安装前准备&#34;&gt;安装前准备
&lt;/h2&gt;&lt;p&gt;使用 Codex App 前，建议先准备好三个基础工具：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Node.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;VS Code&lt;/code&gt; 或你常用的 IDE&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Codex App 支持 macOS 和 Windows。安装后使用 ChatGPT 账号登录，首次进入时可以选择主要使用场景，例如编程或日常工作。Codex 会根据选择预装一部分插件和 Skills，后续也可以在设置和插件市场里调整。&lt;/p&gt;
&lt;p&gt;Windows 和 macOS 的主要功能大体一致，但部分电脑自动化能力可能依赖具体平台和插件支持，实际以你当前版本显示为准。&lt;/p&gt;
&lt;h2 id=&#34;界面结构项目任务和对话&#34;&gt;界面结构：项目、任务和对话
&lt;/h2&gt;&lt;p&gt;Codex App 是典型的三栏布局：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;左侧：项目、任务、历史对话、插件和自动化入口。&lt;/li&gt;
&lt;li&gt;中间：当前对话窗口。&lt;/li&gt;
&lt;li&gt;右侧：文件、浏览器、终端、运行结果等多功能区域。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一个项目通常对应一个本地文件夹。你可以在同一个项目里开多个对话，也可以同时打开多个项目，让不同 agent 并行执行任务。&lt;/p&gt;
&lt;p&gt;任务列表会显示不同状态：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;正在运行：agent 仍在执行。&lt;/li&gt;
&lt;li&gt;等待批准：需要你确认权限、联网、安装依赖或执行高风险操作。&lt;/li&gt;
&lt;li&gt;已完成：任务已经结束，可以查看结果或继续追问。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这比在多个终端窗口里来回切换更直观，也更适合同时管理多个 AI 任务。&lt;/p&gt;
&lt;h2 id=&#34;沙盒与权限控制&#34;&gt;沙盒与权限控制
&lt;/h2&gt;&lt;p&gt;Codex App 的权限体系围绕沙盒展开。默认情况下，当前项目文件夹会成为 agent 的主要工作范围。&lt;/p&gt;
&lt;p&gt;常见权限边界包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以读取和修改项目目录内的文件。&lt;/li&gt;
&lt;li&gt;默认不能随意修改项目外文件。&lt;/li&gt;
&lt;li&gt;默认会限制联网或高风险命令。&lt;/li&gt;
&lt;li&gt;需要越权时，会向用户申请批准。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;比较实用的模式是“自动审查”：低风险操作由系统自动放行，高风险操作再交给用户确认。这样既能减少频繁弹窗，又能避免 agent 在不知情的情况下执行危险操作。&lt;/p&gt;
&lt;p&gt;“完全访问”要谨慎开启。它适合你明确知道 agent 要做什么，并且项目已经有 Git 备份、重要文件也有额外备份的场景。日常使用不建议长期保持完全访问。&lt;/p&gt;
&lt;h2 id=&#34;上下文模型和额度&#34;&gt;上下文、模型和额度
&lt;/h2&gt;&lt;p&gt;Codex App 会显示当前对话的上下文使用情况。对话越长，历史内容越多，模型需要处理的上下文也越大。&lt;/p&gt;
&lt;p&gt;实用建议是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个任务完成后，优先开新对话。&lt;/li&gt;
&lt;li&gt;长对话可以手动压缩，但不要把压缩当成万能记忆。&lt;/li&gt;
&lt;li&gt;复杂任务先写清楚目标、边界和验收标准。&lt;/li&gt;
&lt;li&gt;不要把大量无关日志、报错和文件一次性塞进对话。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;模型选择上，可以根据任务复杂度调整思考强度。简单修改、文案整理、重复任务不一定需要最高规格模型；架构迁移、疑难 bug、跨文件重构则更适合使用更强模型。&lt;/p&gt;
&lt;p&gt;如果界面里有快速模式，也要注意它通常会带来更高的额度消耗。赶时间时可以开，日常不必默认开启。&lt;/p&gt;
&lt;h2 id=&#34;图片生成与多模态输入&#34;&gt;图片生成与多模态输入
&lt;/h2&gt;&lt;p&gt;Codex App 可以接收图片和文件作为上下文，也可以在合适场景中调用图像生成能力。&lt;/p&gt;
&lt;p&gt;这对前端和内容类项目很有用。例如你可以让 Codex：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;根据截图修正页面样式。&lt;/li&gt;
&lt;li&gt;替换网页中的不合适配图。&lt;/li&gt;
&lt;li&gt;生成产品图、轮播图或页面素材。&lt;/li&gt;
&lt;li&gt;根据 UI 截图指出需要修改的位置。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更高效的用法是：不要只说“改好看一点”，而是结合截图指出具体问题，例如“这个卡片间距太大”“这里的图和服务场景不匹配”“把地图区域做得更清楚”。&lt;/p&gt;
&lt;h2 id=&#34;steer任务执行中及时纠偏&#34;&gt;Steer：任务执行中及时纠偏
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Steer&lt;/code&gt; 可以理解成“执行中接管方向”。当 agent 已经开始执行，但你发现它理解错了方向，不应该等它全部跑完再改。&lt;/p&gt;
&lt;p&gt;这时可以使用引导功能，把新的指令插入当前执行流程，让 Codex 及时修正路线。&lt;/p&gt;
&lt;p&gt;适合使用 Steer 的场景包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;agent 误解了需求。&lt;/li&gt;
&lt;li&gt;生成的页面风格明显不对。&lt;/li&gt;
&lt;li&gt;正在执行的方案成本太高。&lt;/li&gt;
&lt;li&gt;你临时补充了关键约束。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一般建议保留默认排队行为，只在确实需要干预时手动使用 Steer。这样既不会打乱正常任务，也能在关键时刻把方向拉回来。&lt;/p&gt;
&lt;h2 id=&#34;计划模式和内置浏览器&#34;&gt;计划模式和内置浏览器
&lt;/h2&gt;&lt;p&gt;复杂任务建议先开计划模式。计划模式下，Codex 不会马上改代码，而是先输出方案，必要时还会用卡片形式追问关键选择。&lt;/p&gt;
&lt;p&gt;适合开计划模式的任务：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;框架迁移，例如从普通 React 项目迁到 Next.js。&lt;/li&gt;
&lt;li&gt;大范围重构。&lt;/li&gt;
&lt;li&gt;涉及数据库、认证、部署的功能。&lt;/li&gt;
&lt;li&gt;你还没想清楚技术路线的需求。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Codex App 的右侧区域可以打开内置浏览器，用来预览本地开发服务。你可以在页面上做批注，让 Codex 按具体 UI 位置修改问题。这种“看页面、点位置、让 AI 改”的流程，比纯文字描述更适合前端调试。&lt;/p&gt;
&lt;h2 id=&#34;gitide-和代码回滚&#34;&gt;Git、IDE 和代码回滚
&lt;/h2&gt;&lt;p&gt;Codex App 不是完整 IDE。它可以查看代码、批注代码，但真正的手写编辑仍然更适合交给 VS Code、Cursor、Windsurf 等 IDE。&lt;/p&gt;
&lt;p&gt;建议每个 Codex 项目都尽早初始化 Git：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;让 Codex 创建或检查 &lt;code&gt;.gitignore&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;在完成一个可用状态后提交一次。&lt;/li&gt;
&lt;li&gt;每次大改前确保有干净提交点。&lt;/li&gt;
&lt;li&gt;不满意时用 Git 回滚代码。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果只回滚对话历史，代码不会自动跟着回滚。比较稳的做法是：对话层面回到合适节点，代码层面用 Git commit hash 回到对应状态。&lt;/p&gt;
&lt;h2 id=&#34;worktree并行开发多个方向&#34;&gt;Worktree：并行开发多个方向
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;git worktree&lt;/code&gt; 是 Codex App 里非常适合并行 agent 的能力。&lt;/p&gt;
&lt;p&gt;它的本质是：基于同一个仓库创建多个独立工作目录，每个目录对应不同分支。这样你可以让不同 agent 在不同文件夹里同时开发，不互相覆盖。&lt;/p&gt;
&lt;p&gt;典型用法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个 worktree 优化客户评价组件。&lt;/li&gt;
&lt;li&gt;一个 worktree 调整门店信息和地图布局。&lt;/li&gt;
&lt;li&gt;两个任务完成后分别合并回主干。&lt;/li&gt;
&lt;li&gt;合并完成后删除临时 worktree。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这比在同一个目录里让多个 agent 同时改代码稳得多。遇到冲突时，也可以按正常 Git 流程 review 和合并。&lt;/p&gt;
&lt;h2 id=&#34;云端运行环境&#34;&gt;云端运行环境
&lt;/h2&gt;&lt;p&gt;Codex 不只能在本机工作，也可以把任务委托到云端环境执行。&lt;/p&gt;
&lt;p&gt;云端运行适合这些场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;出门在外，手边只有手机。&lt;/li&gt;
&lt;li&gt;希望 agent 在后台跑长任务。&lt;/li&gt;
&lt;li&gt;代码已经同步到 GitHub，需要让 Codex 基于远端仓库修改。&lt;/li&gt;
&lt;li&gt;希望通过 PR 形式审查和合并改动。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;典型流程是：先把本地代码推到 GitHub，再让 Codex 在云端环境中拉取仓库、执行任务、生成改动，最后以 PR 或 diff 的方式交给你审核。&lt;/p&gt;
&lt;p&gt;本地继续开发时，要记得把远端最新改动同步回来。&lt;/p&gt;
&lt;h2 id=&#34;记忆系统写好-agentsmd&#34;&gt;记忆系统：写好 AGENTS.md
&lt;/h2&gt;&lt;p&gt;新对话默认没有完整历史记忆。项目一复杂，如果每次都重新解释背景，会很浪费。&lt;/p&gt;
&lt;p&gt;最通用的做法，是在项目根目录维护 &lt;code&gt;AGENTS.md&lt;/code&gt;。这个文件可以记录：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;项目目标和主要技术栈。&lt;/li&gt;
&lt;li&gt;常用命令。&lt;/li&gt;
&lt;li&gt;目录结构说明。&lt;/li&gt;
&lt;li&gt;代码风格和命名约定。&lt;/li&gt;
&lt;li&gt;禁止事项，例如不要批量删除文件。&lt;/li&gt;
&lt;li&gt;测试、构建和部署规则。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你也可以让 Codex 先通读项目，再生成一版 &lt;code&gt;AGENTS.md&lt;/code&gt;，然后人工审一遍。复杂项目里，这个文件非常值得维护。&lt;/p&gt;
&lt;p&gt;全局规则也要谨慎。适合写入所有项目都通用的安全约束，例如“不要递归删除目录”“执行破坏性操作前必须确认”。不要把某个项目的细节写进全局规则，否则会污染其他项目。&lt;/p&gt;
&lt;h2 id=&#34;插件和自动化&#34;&gt;插件和自动化
&lt;/h2&gt;&lt;p&gt;插件用于把外部服务接入 Codex，例如 GitHub、Gmail、Google Drive、数据库、部署平台等。&lt;/p&gt;
&lt;p&gt;插件的价值在于减少复制粘贴。比如你可以让 Codex：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;查看某个 GitHub 仓库的 star 趋势。&lt;/li&gt;
&lt;li&gt;整理邮件内容并发给自己。&lt;/li&gt;
&lt;li&gt;定期执行某个检查任务。&lt;/li&gt;
&lt;li&gt;把结果写成摘要。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;自动化则适合重复任务。例如每周五下午检查一次仓库数据，并发送邮件报告。简单自动化任务通常不需要最高规格模型，选择较轻量的模型即可。&lt;/p&gt;
&lt;h2 id=&#34;skills把工作流变成可复用能力&#34;&gt;Skills：把工作流变成可复用能力
&lt;/h2&gt;&lt;p&gt;Skills 是 Codex 的“专业说明书”。它不是单次提示词，而是把某类任务的流程、规范、脚本和注意事项沉淀下来，让 Codex 后续稳定复用。&lt;/p&gt;
&lt;p&gt;常见来源有三类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;官方 Skills。&lt;/li&gt;
&lt;li&gt;第三方 Skills。&lt;/li&gt;
&lt;li&gt;自己编写的 Skills。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;适合做成 Skill 的工作：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;把字幕整理成图文笔记。&lt;/li&gt;
&lt;li&gt;按公司规范写周报。&lt;/li&gt;
&lt;li&gt;批量处理图片或文档。&lt;/li&gt;
&lt;li&gt;固定格式的代码审查。&lt;/li&gt;
&lt;li&gt;特定框架的项目初始化。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果某个提示词你已经复制粘贴了很多次，就值得考虑把它做成 Skill。&lt;/p&gt;
&lt;h2 id=&#34;mcp接入外部工具和数据库&#34;&gt;MCP：接入外部工具和数据库
&lt;/h2&gt;&lt;p&gt;MCP 可以理解成给大模型使用的标准化工具协议。通过 MCP，Codex 可以调用外部服务完成更具体的任务。&lt;/p&gt;
&lt;p&gt;例如接入 Supabase 后，可以让 Codex：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;创建数据表。&lt;/li&gt;
&lt;li&gt;读取数据库结构。&lt;/li&gt;
&lt;li&gt;修改后端接口。&lt;/li&gt;
&lt;li&gt;把前端表单提交到数据库。&lt;/li&gt;
&lt;li&gt;根据数据库状态调试问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这类能力很强，但也要注意权限边界。数据库、生产环境、部署平台、邮件账号都属于高风险资源。第一次接入时，最好使用测试项目和低权限账号。&lt;/p&gt;
&lt;h2 id=&#34;部署插件&#34;&gt;部署插件
&lt;/h2&gt;&lt;p&gt;部署平台插件可以让 Codex 直接完成构建和发布，例如把前端项目部署到 Netlify 一类平台。&lt;/p&gt;
&lt;p&gt;这类插件适合小型网站、原型页面、内部工具和展示项目。实际使用时建议注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;部署前先跑本地构建。&lt;/li&gt;
&lt;li&gt;环境变量不要直接写进代码。&lt;/li&gt;
&lt;li&gt;发布后检查页面是否能正常访问。&lt;/li&gt;
&lt;li&gt;生产项目要保留人工 review。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI 可以帮你打通发布流程，但发布权限仍然要谨慎管理。&lt;/p&gt;
&lt;h2 id=&#34;电脑自动化&#34;&gt;电脑自动化
&lt;/h2&gt;&lt;p&gt;在支持的平台和插件环境里，Codex 还可以操作浏览器或桌面应用，完成更接近 RPA 的任务。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;打开聊天软件并准备一条消息。&lt;/li&gt;
&lt;li&gt;浏览项目看板，汇总任务状态。&lt;/li&gt;
&lt;li&gt;生成英文简报。&lt;/li&gt;
&lt;li&gt;在你确认后发送给指定对象。&lt;/li&gt;
&lt;li&gt;把这套流程做成定时自动化。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这类功能很有想象力，但也最需要安全边界。凡是涉及发消息、发邮件、提交表单、付款、删除数据的操作，都应该保留人工确认。&lt;/p&gt;
&lt;h2 id=&#34;使用建议&#34;&gt;使用建议
&lt;/h2&gt;&lt;p&gt;Codex App 的正确打开方式，不是让它一次性全自动接管一切，而是把任务拆清楚，让它在受控环境里高效执行。&lt;/p&gt;
&lt;p&gt;推荐习惯：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个项目先初始化 Git。&lt;/li&gt;
&lt;li&gt;复杂任务先开计划模式。&lt;/li&gt;
&lt;li&gt;并行任务优先用 worktree。&lt;/li&gt;
&lt;li&gt;项目规则写进 &lt;code&gt;AGENTS.md&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;高风险操作保留人工确认。&lt;/li&gt;
&lt;li&gt;重复流程沉淀成 Skill 或自动化。&lt;/li&gt;
&lt;li&gt;插件和 MCP 先在测试环境验证。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;参考资料&#34;&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://openai.com/index/introducing-the-codex-app/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Introducing the Codex app - OpenAI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/11369540-codex-in-chatgpt&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Using Codex with your ChatGPT plan - OpenAI Help Center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://openai.com/academy/codex-plugins-and-skills/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Plugins and skills - OpenAI Academy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;Codex App 的重点不是“多一个 AI 聊天窗口”，而是把 AI 编程变成一个可管理的工作台：本地项目、云端任务、Git、worktree、插件、Skills、MCP 和自动化都能串起来。&lt;/p&gt;
&lt;p&gt;真正用好它的关键，是在“放权”和“控制”之间找到平衡。小任务可以大胆交给 Codex，复杂任务先让它计划，高风险动作必须确认。这样它才会从一个会写代码的助手，变成可以长期协作的工程工具。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>ChatGPT 和 Codex 登录要求验证手机号，可能是什么原因</title>
        <link>https://knightli.com/2026/05/05/chatgpt-codex-phone-verification-plus/</link>
        <pubDate>Tue, 05 May 2026 23:57:50 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/05/chatgpt-codex-phone-verification-plus/</guid>
        <description>&lt;p&gt;最近有些用户会遇到一个情况：ChatGPT 账号已经注册成功，但登录 ChatGPT 或 Codex 时，系统又要求验证手机号。尤其是在使用 Codex 时，这个提示更容易让人困惑：账号明明能注册，为什么登录工具时还要补手机号？&lt;/p&gt;
&lt;p&gt;这类问题通常和账号风控、免费额度滥用、网络环境以及账号安全策略有关。下面把常见原因和处理思路整理一下。&lt;/p&gt;
&lt;h2 id=&#34;为什么会要求验证手机号&#34;&gt;为什么会要求验证手机号
&lt;/h2&gt;&lt;p&gt;最直接的原因是风控升级。&lt;/p&gt;
&lt;p&gt;Codex 面向用户开放后，免费额度会吸引大量真实用户试用，也会吸引批量注册、批量领取额度的行为。如果有人用注册机批量创建账号，再用这些账号消耗免费额度，平台就会更容易收紧验证策略。&lt;/p&gt;
&lt;p&gt;从用户侧看到的结果就是：原本只需要邮箱或第三方登录的账号，在登录 ChatGPT 或 Codex 时，突然被要求补充手机号验证。&lt;/p&gt;
&lt;p&gt;这不一定代表你的账号一定有问题，也可能是触发了更高风险的登录环境。例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用了被大量用户共享的网络出口。&lt;/li&gt;
&lt;li&gt;当前 IP 段被频繁用于注册或异常登录。&lt;/li&gt;
&lt;li&gt;账号刚注册不久，却马上访问高消耗工具。&lt;/li&gt;
&lt;li&gt;登录设备、地区、网络频繁变化。&lt;/li&gt;
&lt;li&gt;免费账号使用行为和批量账号相似。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果近期出现账号异常、登录受限或误封，也可能和网络环境被连带标记有关。尤其是多人共享的节点，风险会明显更高。&lt;/p&gt;
&lt;h2 id=&#34;codex-为什么更容易触发&#34;&gt;Codex 为什么更容易触发
&lt;/h2&gt;&lt;p&gt;Codex 和普通聊天不同，它更接近开发工具，可能涉及更高的资源消耗，也更容易被批量账号拿来消耗免费额度。&lt;/p&gt;
&lt;p&gt;所以同一个账号在普通 ChatGPT 页面里看起来正常，到了 Codex 登录流程里却触发手机号验证，并不奇怪。可以把它理解为：不同产品入口会有不同的风险判断。&lt;/p&gt;
&lt;p&gt;对正常用户来说，这类验证通常不是为了为难单个用户，而是为了限制批量注册和免费额度滥用。但如果你的网络环境不干净，也会被误伤。&lt;/p&gt;
&lt;h2 id=&#34;处理方法一升级-plus&#34;&gt;处理方法一：升级 Plus
&lt;/h2&gt;&lt;p&gt;如果你是长期使用 ChatGPT 或 Codex，最简单的处理方式是升级 ChatGPT Plus。&lt;/p&gt;
&lt;p&gt;从实际使用体验看，付费账号通常比免费账号更不容易触发这类额度滥用风控。Plus 账号本身也更适合稳定使用 Codex、ChatGPT 高级模型和其他高频功能。&lt;/p&gt;
&lt;p&gt;不过要注意：升级 Plus 并不等于永远不会再触发验证。如果升级后仍然要求手机号，常见原因还是网络环境问题。&lt;/p&gt;
&lt;p&gt;这时可以优先检查：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;是否使用了大量用户共享的网络。&lt;/li&gt;
&lt;li&gt;当前出口 IP 是否频繁变化。&lt;/li&gt;
&lt;li&gt;是否长期使用低质量代理或公共节点。&lt;/li&gt;
&lt;li&gt;是否同一网络下有大量 OpenAI 账号登录。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果条件允许，换一个更稳定、更干净的网络环境再登录，通常比反复重试更有效。&lt;/p&gt;
&lt;h2 id=&#34;处理方法二检查网络环境&#34;&gt;处理方法二：检查网络环境
&lt;/h2&gt;&lt;p&gt;很多登录验证问题，看起来像账号问题，本质上是网络问题。&lt;/p&gt;
&lt;p&gt;如果某个出口 IP 被大量用户共用，或者曾经被用于批量注册、异常登录、自动化请求，就更容易被标记。此时即使你是正常用户，也可能在登录 ChatGPT 或 Codex 时被要求额外验证。&lt;/p&gt;
&lt;p&gt;可以从这几个角度排查：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;换一个更稳定的网络环境。&lt;/li&gt;
&lt;li&gt;避免使用公开、廉价、多人共享的节点。&lt;/li&gt;
&lt;li&gt;尽量减少短时间内频繁切换地区。&lt;/li&gt;
&lt;li&gt;不要在同一浏览器里频繁切换多个账号。&lt;/li&gt;
&lt;li&gt;如果使用代理，优先选择质量更稳定、滥用更少的线路。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;也可以借助第三方网络质量检测工具查看当前 IP 的风险情况，但检测结果只能作为参考，不能完全代表 OpenAI 的内部判断。&lt;/p&gt;
&lt;h2 id=&#34;处理方法三按要求完成手机号验证&#34;&gt;处理方法三：按要求完成手机号验证
&lt;/h2&gt;&lt;p&gt;如果系统明确要求手机号验证，最稳妥的方式仍然是按要求完成验证。&lt;/p&gt;
&lt;p&gt;建议优先使用自己可长期接收验证码的号码。这样以后如果账号出现安全验证、恢复登录、异常提醒，也能继续处理。&lt;/p&gt;
&lt;p&gt;不建议把重要账号绑定到来路不明、多人共用或无法长期使用的号码上。短期看可能能通过验证，长期看会带来账号找回、安全审计和二次验证风险。&lt;/p&gt;
&lt;p&gt;如果你使用的是工作账号、团队账号或长期依赖的开发账号，更应该避免使用不可控的临时号码。账号安全比临时省事更重要。&lt;/p&gt;
&lt;h2 id=&#34;升级-plus-时要注意什么&#34;&gt;升级 Plus 时要注意什么
&lt;/h2&gt;&lt;p&gt;如果你准备升级 Plus，可以先确认几件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;账号本身可以正常登录。&lt;/li&gt;
&lt;li&gt;当前网络环境稳定，不频繁跳地区。&lt;/li&gt;
&lt;li&gt;支付方式可靠，不要使用来源不明的代付。&lt;/li&gt;
&lt;li&gt;升级后保留好付款记录和账号邮箱。&lt;/li&gt;
&lt;li&gt;不要把账号借给多人共用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;很多账号问题并不是出在 Plus 本身，而是出在升级前后的网络、支付和共享使用习惯上。一个账号如果长期多人共用、频繁异地登录、经常切换环境，即使付费也可能触发安全验证。&lt;/p&gt;
&lt;p&gt;如果只是偶尔试用，免费账号也可以继续用。但如果你已经把 Codex 当成日常开发工具，Plus 会更适合长期使用。&lt;/p&gt;
&lt;h2 id=&#34;不建议继续薅免费额度&#34;&gt;不建议继续薅免费额度
&lt;/h2&gt;&lt;p&gt;Codex 这类工具的免费额度本来是为了让正常用户体验和试用。如果大量批量账号持续消耗免费额度，平台最终只能继续提高风控强度。&lt;/p&gt;
&lt;p&gt;结果就是正常用户也会受到影响：登录更麻烦，验证更多，封禁误伤更多，账号使用成本更高。&lt;/p&gt;
&lt;p&gt;对真正把 Codex 用在写代码、改项目、跑工程任务的人来说，与其把时间花在规避风控上，不如把账号和网络环境整理干净。长期看，这比反复注册新账号、切换节点、处理验证问题更省事。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;ChatGPT 或 Codex 登录时要求验证手机号，通常和账号风控、免费额度滥用、网络环境风险有关。它不一定代表账号本身违规，但说明当前登录环境或账号状态触发了更高等级的验证。&lt;/p&gt;
&lt;p&gt;处理顺序可以很简单：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先检查网络环境，避开多人共享和高风险出口。&lt;/li&gt;
&lt;li&gt;长期使用就考虑升级 Plus。&lt;/li&gt;
&lt;li&gt;如果系统要求手机号验证，优先使用自己可长期控制的号码完成。&lt;/li&gt;
&lt;li&gt;避免批量注册、共享账号和频繁切换登录环境。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;稳定使用 AI 工具的核心不是一直绕过验证，而是让账号、网络和使用方式都尽量正常。这样才能减少登录麻烦，也能降低后续被误伤的概率。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>OpenAI 推出 Advanced Account Security：ChatGPT 和 Codex 账号多了一层高强度保护</title>
        <link>https://knightli.com/2026/05/01/openai-advanced-account-security/</link>
        <pubDate>Fri, 01 May 2026 06:15:29 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/01/openai-advanced-account-security/</guid>
        <description>&lt;p&gt;OpenAI 在 2026 年 4 月 30 日推出了 &lt;code&gt;Advanced Account Security&lt;/code&gt;，这是面向 ChatGPT 账号的可选高级安全设置。&lt;/p&gt;
&lt;p&gt;它主要服务两类用户：一类是记者、民选官员、政治异议人士、研究人员等更容易遭遇定向攻击的人；另一类是希望给 ChatGPT 和 Codex 账号加上更强保护的安全敏感用户。&lt;/p&gt;
&lt;p&gt;这项功能开启后，不只保护 ChatGPT，也会保护同一登录账号下访问的 Codex。&lt;/p&gt;
&lt;h2 id=&#34;为什么-chatgpt-账号需要更高安全等级&#34;&gt;为什么 ChatGPT 账号需要更高安全等级
&lt;/h2&gt;&lt;p&gt;现在很多人会把 ChatGPT 用在越来越私密、越来越高风险的工作里。&lt;/p&gt;
&lt;p&gt;一个 ChatGPT 账号里可能包含：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;个人问题和长期对话&lt;/li&gt;
&lt;li&gt;工作文档与项目上下文&lt;/li&gt;
&lt;li&gt;已连接工具和工作流&lt;/li&gt;
&lt;li&gt;Codex 里的代码与开发任务&lt;/li&gt;
&lt;li&gt;企业、研究或安全相关材料&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果账号被接管，损失不只是聊天记录泄露。攻击者还可能访问连接的工具、查看敏感上下文，甚至干扰用户正在进行的工作。&lt;/p&gt;
&lt;p&gt;所以 OpenAI 这次推出的不是一个普通登录选项，而是一组更严格的账号保护措施。&lt;/p&gt;
&lt;h2 id=&#34;advanced-account-security-包含哪些保护&#34;&gt;Advanced Account Security 包含哪些保护
&lt;/h2&gt;&lt;p&gt;OpenAI 把这项能力放在 ChatGPT 网页端账号的 Security 设置里，用户可以主动开启。&lt;/p&gt;
&lt;p&gt;开启后，它会从几个方面提高账号安全性。&lt;/p&gt;
&lt;p&gt;第一，登录方式更强。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Advanced Account Security&lt;/code&gt; 要求使用 &lt;code&gt;passkeys&lt;/code&gt; 或实体安全密钥，并禁用基于密码的登录。这样做的目的，是让更抗钓鱼的登录方式成为默认选择。&lt;/p&gt;
&lt;p&gt;第二，账号恢复更严格。&lt;/p&gt;
&lt;p&gt;传统账号恢复经常依赖邮箱或短信。如果攻击者控制了用户的邮箱或手机号，就可能借此重置账号。为降低这个风险，Advanced Account Security 会禁用邮件和 SMS 恢复，改用更强的恢复方式，例如备用 passkeys、安全密钥和恢复密钥。&lt;/p&gt;
&lt;p&gt;这里有一个重要代价：开启后，账号恢复会更依赖用户自己保管这些恢复方式。OpenAI 明确说明，已开启该功能的用户如果丢失恢复手段，OpenAI Support 无法协助恢复账号。&lt;/p&gt;
&lt;p&gt;第三，会话时间更短，管理更清晰。&lt;/p&gt;
&lt;p&gt;OpenAI 会缩短登录会话，以降低设备或活跃会话被盗用后的暴露窗口。用户也会收到登录提醒，并可以查看和管理当前登录的设备会话。&lt;/p&gt;
&lt;p&gt;第四，自动排除训练。&lt;/p&gt;
&lt;p&gt;对处理敏感信息的人来说，不让对话用于模型训练是一项重要隐私设置。开启 Advanced Account Security 后，这个偏好会自动生效：这些账号的对话不会用于训练 OpenAI 模型。&lt;/p&gt;
&lt;h2 id=&#34;与-yubico-合作推广实体安全密钥&#34;&gt;与 Yubico 合作推广实体安全密钥
&lt;/h2&gt;&lt;p&gt;OpenAI 还宣布与 Yubico 合作，给用户提供定制的安全密钥组合。&lt;/p&gt;
&lt;p&gt;其中包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;YubiKey C Nano&lt;/code&gt;：适合长期插在笔记本上，日常登录摩擦更小&lt;/li&gt;
&lt;li&gt;&lt;code&gt;YubiKey C NFC&lt;/code&gt;：适合作为备用，也方便在笔记本和移动设备之间使用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OpenAI 表示，用户也可以使用其他符合 FIDO 标准的实体安全密钥，或者使用软件 passkeys。&lt;/p&gt;
&lt;p&gt;这说明 Advanced Account Security 并不绑定某一种硬件，而是围绕抗钓鱼认证方式设计。&lt;/p&gt;
&lt;h2 id=&#34;cyber-可信访问用户会被要求开启&#34;&gt;Cyber 可信访问用户会被要求开启
&lt;/h2&gt;&lt;p&gt;OpenAI 还提到，针对 &lt;code&gt;Trusted Access for Cyber&lt;/code&gt; 的个人成员，如果他们要访问更强、更宽松的网络安全模型，从 2026 年 6 月 1 日开始将被要求开启 Advanced Account Security。&lt;/p&gt;
&lt;p&gt;组织用户可以用另一种方式满足要求：证明自己的单点登录流程已经采用抗钓鱼认证。&lt;/p&gt;
&lt;p&gt;这个安排很合理。越强的模型能力越需要更强的账号保护，尤其是面向网络安全研究、漏洞分析和红队等场景时，账号本身就会成为高价值目标。&lt;/p&gt;
&lt;h2 id=&#34;适合谁开启&#34;&gt;适合谁开启
&lt;/h2&gt;&lt;p&gt;这项功能不一定适合所有人。&lt;/p&gt;
&lt;p&gt;如果只是普通聊天，且不想承担更严格账号恢复带来的复杂性，可以先观望。&lt;/p&gt;
&lt;p&gt;但以下用户值得认真考虑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;经常在 ChatGPT 中处理敏感工作材料的人&lt;/li&gt;
&lt;li&gt;使用 Codex 处理私有代码仓库的人&lt;/li&gt;
&lt;li&gt;记者、公共事务人员、研究人员、企业高管等高风险用户&lt;/li&gt;
&lt;li&gt;网络安全从业者&lt;/li&gt;
&lt;li&gt;已经习惯使用 passkeys 或实体安全密钥的人&lt;/li&gt;
&lt;li&gt;对账号被钓鱼、短信劫持或邮箱接管特别敏感的人&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;开启之前，最好先准备好备用 passkey、安全密钥和恢复密钥，并确认它们被妥善保存。否则，安全性提高的同时，账号恢复难度也会明显提高。&lt;/p&gt;
&lt;h2 id=&#34;这对-ai-产品意味着什么&#34;&gt;这对 AI 产品意味着什么
&lt;/h2&gt;&lt;p&gt;Advanced Account Security 不是一个模型能力更新，但它反映了 AI 产品正在进入更高风险的使用阶段。&lt;/p&gt;
&lt;p&gt;当 ChatGPT 和 Codex 开始承载工作流、代码、文档、企业连接器和长期上下文时，账号就不再只是“登录聊天工具”的入口，而是 AI 工作环境的钥匙。&lt;/p&gt;
&lt;p&gt;这类产品越像个人工作台，账号安全、恢复机制、会话管理和训练数据控制就越重要。&lt;/p&gt;
&lt;p&gt;OpenAI 这次把 passkeys、实体安全密钥、恢复限制、会话管理和训练排除放到同一个设置里，方向是对的。它让高风险用户可以用一个明确入口，把账号保护提升到更适合敏感工作的级别。&lt;/p&gt;
&lt;h2 id=&#34;小结&#34;&gt;小结
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Advanced Account Security&lt;/code&gt; 可以理解为 ChatGPT 和 Codex 的高安全模式。&lt;/p&gt;
&lt;p&gt;它通过更强登录、更严格恢复、更短会话、登录提醒和自动排除训练，降低账号被接管后的风险。代价是用户需要更认真地管理自己的恢复方式，因为开启后传统邮件和短信恢复不再可用，OpenAI Support 也无法替用户兜底。&lt;/p&gt;
&lt;p&gt;如果你已经把 ChatGPT 或 Codex 用在重要工作里，尤其是涉及私有代码、敏感文档或高风险身份，这项功能值得关注。&lt;/p&gt;
&lt;p&gt;参考链接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://openai.com/index/advanced-account-security/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Introducing Advanced Account Security - OpenAI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>mattpocock/skills：给 AI 编程 Agent 准备的实用技能集合</title>
        <link>https://knightli.com/2026/05/01/mattpocock-skills-ai-agent-coding-workflows/</link>
        <pubDate>Fri, 01 May 2026 03:43:20 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/01/mattpocock-skills-ai-agent-coding-workflows/</guid>
        <description>&lt;p&gt;&lt;code&gt;mattpocock/skills&lt;/code&gt; 是 Matt Pocock 公开的一组 AI 编程 agent skills。&lt;/p&gt;
&lt;p&gt;它不是一个完整的应用，也不是一个新的聊天客户端，而是一套可以给 AI 编程助手使用的工作技能。它的思路很实用：把 AI 编程里经常出现的问题拆成一个个小技能，让 Agent 在合适的任务里调用，而不是每次都靠一大段提示词硬撑。&lt;/p&gt;
&lt;p&gt;如果你经常使用 Claude Code、Codex、Cursor 或类似的 AI 编程工具，这类 skills 很值得关注。因为真正影响 AI 编程体验的，往往不是“模型会不会写代码”，而是它能不能按你的工作方式推进任务。&lt;/p&gt;
&lt;h2 id=&#34;它解决什么问题&#34;&gt;它解决什么问题
&lt;/h2&gt;&lt;p&gt;AI 编程助手很强，但也很容易出问题。&lt;/p&gt;
&lt;p&gt;常见情况包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;还没理解需求就开始改代码&lt;/li&gt;
&lt;li&gt;一次性改太多文件&lt;/li&gt;
&lt;li&gt;输出解释很多，真正有用的行动很少&lt;/li&gt;
&lt;li&gt;遇到报错后盲目尝试&lt;/li&gt;
&lt;li&gt;没有及时运行测试或检查&lt;/li&gt;
&lt;li&gt;忽略项目里已有模式&lt;/li&gt;
&lt;li&gt;为了完成任务引入不必要的抽象&lt;/li&gt;
&lt;li&gt;写完代码后没有真正 review 风险&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些问题不一定是模型能力不够，而是工作流没有被约束好。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mattpocock/skills&lt;/code&gt; 的价值在于，把这些常见失败模式拆成可以复用的操作方式，让 Agent 在不同场景下更像一个有经验的工程协作者。&lt;/p&gt;
&lt;h2 id=&#34;skills-是什么&#34;&gt;Skills 是什么
&lt;/h2&gt;&lt;p&gt;在 AI Agent 语境里，skill 可以理解成一段可复用的任务说明、工作方法或专业流程。&lt;/p&gt;
&lt;p&gt;它不一定是代码插件，也不一定必须调用外部服务。很多时候，一个 skill 就是一套明确规则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;什么时候使用&lt;/li&gt;
&lt;li&gt;先做什么&lt;/li&gt;
&lt;li&gt;不要做什么&lt;/li&gt;
&lt;li&gt;需要输出什么&lt;/li&gt;
&lt;li&gt;怎么判断任务完成&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这和普通提示词模板有点像，但粒度更接近“任务能力”。&lt;/p&gt;
&lt;p&gt;普通提示词模板通常是用户每次临时复制粘贴；skills 则更适合作为 agent 工具箱的一部分，让 Agent 根据任务选择合适流程。&lt;/p&gt;
&lt;h2 id=&#34;为什么要小而可组合&#34;&gt;为什么要小而可组合
&lt;/h2&gt;&lt;p&gt;README 中强调这些 skills 是小而可组合的。&lt;/p&gt;
&lt;p&gt;这个方向很重要。&lt;/p&gt;
&lt;p&gt;如果一个 skill 试图包办所有事情，它很快就会变成新的大提示词：又长、又模糊、又难维护。小技能的优势是边界清楚。&lt;/p&gt;
&lt;p&gt;比如一个 skill 专门负责：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先做计划&lt;/li&gt;
&lt;li&gt;修复 TypeScript 错误&lt;/li&gt;
&lt;li&gt;运行测试并根据结果修复&lt;/li&gt;
&lt;li&gt;做代码 review&lt;/li&gt;
&lt;li&gt;总结项目约定&lt;/li&gt;
&lt;li&gt;改进提示词&lt;/li&gt;
&lt;li&gt;清理无用抽象&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些技能可以按任务组合使用。简单任务只用一个技能，复杂任务再串起来。&lt;/p&gt;
&lt;p&gt;这更接近真实工程工作：你不会用同一套流程处理所有问题，而是根据问题选择工具。&lt;/p&gt;
&lt;h2 id=&#34;保留工程师控制权&#34;&gt;保留工程师控制权
&lt;/h2&gt;&lt;p&gt;这个仓库的一个重要取向，是让工程师仍然掌握控制权。&lt;/p&gt;
&lt;p&gt;AI 编程很容易滑向两种极端：&lt;/p&gt;
&lt;p&gt;第一种是完全手动。AI 只是帮你写几行代码，所有上下文、计划、验证都靠你自己盯。&lt;/p&gt;
&lt;p&gt;第二种是完全放手。你把任务丢给 Agent，让它自己大改一通，最后再面对一堆难以审查的 diff。&lt;/p&gt;
&lt;p&gt;skills 的作用是在中间找一个更稳的位置。&lt;/p&gt;
&lt;p&gt;它让 AI 承担更多重复流程，但仍然用规则限制它：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先理解任务再动手&lt;/li&gt;
&lt;li&gt;先阅读相关文件再改&lt;/li&gt;
&lt;li&gt;修改范围要可控&lt;/li&gt;
&lt;li&gt;出现不确定时要回报&lt;/li&gt;
&lt;li&gt;改完要验证&lt;/li&gt;
&lt;li&gt;不能为了炫技重构无关代码&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这不是削弱 AI，而是让 AI 的行动更容易被人类审查和接管。&lt;/p&gt;
&lt;h2 id=&#34;对齐问题&#34;&gt;对齐问题
&lt;/h2&gt;&lt;p&gt;AI 编程失败的第一类问题通常是对齐失败。&lt;/p&gt;
&lt;p&gt;用户想要的是一个很具体的改动，但 Agent 可能理解成一个更大的重构；用户只想修 Bug，它却顺手改了样式；用户希望遵守现有架构，它却引入新模式。&lt;/p&gt;
&lt;p&gt;Skills 可以在任务开始阶段帮助 Agent 做几件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;重述目标&lt;/li&gt;
&lt;li&gt;找出影响范围&lt;/li&gt;
&lt;li&gt;识别已有实现模式&lt;/li&gt;
&lt;li&gt;给出计划&lt;/li&gt;
&lt;li&gt;明确不做哪些事情&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这一步很像工程师开工前的自检。&lt;/p&gt;
&lt;p&gt;如果 Agent 连任务边界都没说清楚，就直接写代码，后面很容易越走越偏。&lt;/p&gt;
&lt;h2 id=&#34;反馈循环问题&#34;&gt;反馈循环问题
&lt;/h2&gt;&lt;p&gt;AI 写代码不能只靠一次生成。&lt;/p&gt;
&lt;p&gt;真实开发里，反馈循环很重要：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;改一小步&lt;/li&gt;
&lt;li&gt;跑测试或类型检查&lt;/li&gt;
&lt;li&gt;看错误&lt;/li&gt;
&lt;li&gt;修正&lt;/li&gt;
&lt;li&gt;再验证&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;很多 Agent 失败，是因为它跳过了中间反馈。它一次性改很多内容，然后凭感觉总结“应该可以工作”。&lt;/p&gt;
&lt;p&gt;Skills 可以把反馈循环显式写进流程里。比如要求 Agent：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;修改后运行相关检查&lt;/li&gt;
&lt;li&gt;如果检查失败，先读错误信息&lt;/li&gt;
&lt;li&gt;不要盲目改无关文件&lt;/li&gt;
&lt;li&gt;每轮修复后重新验证&lt;/li&gt;
&lt;li&gt;最后报告验证结果&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这会让 AI 编程更像真实调试，而不是一次性作文。&lt;/p&gt;
&lt;h2 id=&#34;架构控制问题&#34;&gt;架构控制问题
&lt;/h2&gt;&lt;p&gt;AI 很擅长生成抽象，也很擅长过度生成抽象。&lt;/p&gt;
&lt;p&gt;为了完成一个小需求，它可能新建服务层、工具函数、配置对象、类型包装、适配器，最后让代码比需求本身复杂得多。&lt;/p&gt;
&lt;p&gt;这类问题在大型项目里尤其危险。因为 AI 生成的抽象看起来很“专业”，但它可能不符合项目已有风格，也可能增加维护成本。&lt;/p&gt;
&lt;p&gt;好的 skills 会提醒 Agent：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;优先沿用现有模式&lt;/li&gt;
&lt;li&gt;不引入没有必要的新抽象&lt;/li&gt;
&lt;li&gt;不顺手重构无关区域&lt;/li&gt;
&lt;li&gt;修改要和任务规模匹配&lt;/li&gt;
&lt;li&gt;先理解代码再设计结构&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这能减少“看起来很工程化，实际上更难维护”的输出。&lt;/p&gt;
&lt;h2 id=&#34;review-技能为什么重要&#34;&gt;Review 技能为什么重要
&lt;/h2&gt;&lt;p&gt;写代码和 review 代码是两种不同状态。&lt;/p&gt;
&lt;p&gt;Agent 在写代码时，通常会倾向于证明自己的实现成立。它会解释为什么这样改可以工作，但不一定主动找风险。&lt;/p&gt;
&lt;p&gt;Review skill 的意义，是让 Agent 切换角色：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;找潜在 Bug&lt;/li&gt;
&lt;li&gt;找行为回归&lt;/li&gt;
&lt;li&gt;找遗漏测试&lt;/li&gt;
&lt;li&gt;找边界条件&lt;/li&gt;
&lt;li&gt;找复杂度上升&lt;/li&gt;
&lt;li&gt;找和现有约定不一致的地方&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这对 AI 编程很重要。因为 AI 生成代码的速度很快，如果没有 review，用户很容易被大量 diff 淹没。&lt;/p&gt;
&lt;p&gt;一个好的 review 输出应该优先列问题，而不是先夸实现。它要帮助工程师判断这次改动能不能合并。&lt;/p&gt;
&lt;h2 id=&#34;和普通-rules-文件有什么区别&#34;&gt;和普通 rules 文件有什么区别
&lt;/h2&gt;&lt;p&gt;很多 AI 编程工具都支持 rules、instructions 或 memory。&lt;/p&gt;
&lt;p&gt;这些文件通常记录长期规则，比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;项目技术栈&lt;/li&gt;
&lt;li&gt;命名规范&lt;/li&gt;
&lt;li&gt;测试命令&lt;/li&gt;
&lt;li&gt;不要修改哪些目录&lt;/li&gt;
&lt;li&gt;回答风格偏好&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Skills 更偏任务流程。&lt;/p&gt;
&lt;p&gt;rules 告诉 Agent “长期应该怎么做”，skills 告诉 Agent “面对某类任务时应该怎么执行”。&lt;/p&gt;
&lt;p&gt;两者最好一起用。&lt;/p&gt;
&lt;p&gt;比如 rules 里写项目用 &lt;code&gt;pnpm test&lt;/code&gt;，review skill 里要求改完后检查测试覆盖。这样 Agent 不仅知道命令，也知道什么时候该用。&lt;/p&gt;
&lt;h2 id=&#34;适合什么场景&#34;&gt;适合什么场景
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;mattpocock/skills&lt;/code&gt; 这类仓库适合这些场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;高频使用 AI 编程工具&lt;/li&gt;
&lt;li&gt;经常让 Agent 处理真实代码库&lt;/li&gt;
&lt;li&gt;想减少 AI 越界修改&lt;/li&gt;
&lt;li&gt;想让 Agent 更主动地验证结果&lt;/li&gt;
&lt;li&gt;想把自己的工程习惯沉淀成技能&lt;/li&gt;
&lt;li&gt;想学习别人如何设计 agent workflows&lt;/li&gt;
&lt;li&gt;想把一堆临时提示词整理成可维护的技能集合&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你只是偶尔让 AI 写一个小函数，可能不需要专门维护 skills。&lt;/p&gt;
&lt;p&gt;但如果你已经把 AI 当成长期开发伙伴，skills 会逐渐变得重要。它们相当于给 Agent 配了一套可复用的工作方法。&lt;/p&gt;
&lt;h2 id=&#34;怎么借鉴这个仓库&#34;&gt;怎么借鉴这个仓库
&lt;/h2&gt;&lt;p&gt;即使你不直接使用其中的每个 skill，也可以从这个仓库学到几件事。&lt;/p&gt;
&lt;p&gt;第一，把失败模式写下来。&lt;/p&gt;
&lt;p&gt;不要只在 AI 出错时临时抱怨。把它经常出错的模式整理成规则，下一次让 skill 提前防住。&lt;/p&gt;
&lt;p&gt;第二，技能要短。&lt;/p&gt;
&lt;p&gt;一个 skill 最好解决一个明确问题。越短越容易被正确调用，也越容易维护。&lt;/p&gt;
&lt;p&gt;第三，输出格式要清楚。&lt;/p&gt;
&lt;p&gt;如果你希望 Agent 先列计划、再执行、最后总结验证结果，就把输出结构写清楚。模糊要求通常会得到模糊结果。&lt;/p&gt;
&lt;p&gt;第四，保留人工接管点。&lt;/p&gt;
&lt;p&gt;好的 skill 不应该让 AI 独自跑到很远。遇到不确定、影响范围扩大、测试失败或需要产品判断时，应该让它停下来说明情况。&lt;/p&gt;
&lt;h2 id=&#34;使用时要注意&#34;&gt;使用时要注意
&lt;/h2&gt;&lt;p&gt;第一，不要把所有事情都技能化。&lt;/p&gt;
&lt;p&gt;太多 skills 会让系统变复杂，Agent 也可能不知道该选哪个。先从最高频、最痛的几个场景开始。&lt;/p&gt;
&lt;p&gt;第二，skills 需要迭代。&lt;/p&gt;
&lt;p&gt;第一次写出来的 skill 不一定好。看 AI 实际执行效果，再逐步删减、补充和改写。&lt;/p&gt;
&lt;p&gt;第三，不要让 skill 替代工程判断。&lt;/p&gt;
&lt;p&gt;Skill 可以改善流程，但不能保证实现正确。测试、review、构建检查和人类判断仍然重要。&lt;/p&gt;
&lt;p&gt;第四，注意不同 Agent 的差异。&lt;/p&gt;
&lt;p&gt;Claude Code、Codex、Cursor、Copilot 对 instructions、skills、rules 的支持方式不同。同一套思想可以复用，但具体格式要按工具调整。&lt;/p&gt;
&lt;h2 id=&#34;参考&#34;&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/mattpocock/skills&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;mattpocock/skills&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;最后一句&#34;&gt;最后一句
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;mattpocock/skills&lt;/code&gt; 值得关注的地方，不是里面某一个神奇提示词，而是它展示了一种更实用的 AI 编程思路：把工程经验拆成小技能，再让 Agent 按场景组合使用。&lt;/p&gt;
&lt;p&gt;当 AI 编程从偶尔辅助变成日常工作流，skills 会成为约束 Agent、保留工程师控制权和提升反馈质量的重要工具。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Compound Engineering Plugin：把 AI 编程变成计划、执行、评审的工程循环</title>
        <link>https://knightli.com/2026/05/01/compound-engineering-plugin-ai-coding-workflow/</link>
        <pubDate>Fri, 01 May 2026 03:15:39 +0800</pubDate>
        
        <guid>https://knightli.com/2026/05/01/compound-engineering-plugin-ai-coding-workflow/</guid>
        <description>&lt;p&gt;&lt;code&gt;Compound Engineering Plugin&lt;/code&gt; 是 Every Inc 开源的一个 AI 编程工作流插件。&lt;/p&gt;
&lt;p&gt;它关注的不是“让 AI 更快写一段代码”，而是把 AI 编程放进一个更像工程团队的循环里：先计划，再实现，再评审，再把经验沉淀下来。对经常使用 Claude Code、Codex、Cursor、Copilot 这类工具的人来说，这类插件解决的是工作流问题，而不只是提示词问题。&lt;/p&gt;
&lt;p&gt;AI 编程工具越来越强，但真实项目里最难的往往不是生成代码，而是让它持续按项目规则做事、理解任务边界、避免重复犯错，并在多轮迭代中积累上下文。&lt;/p&gt;
&lt;h2 id=&#34;它解决什么问题&#34;&gt;它解决什么问题
&lt;/h2&gt;&lt;p&gt;很多人使用 AI 编程助手时，流程大概是这样：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;直接描述需求&lt;/li&gt;
&lt;li&gt;让 AI 改代码&lt;/li&gt;
&lt;li&gt;看结果是否能跑&lt;/li&gt;
&lt;li&gt;出错后继续补充说明&lt;/li&gt;
&lt;li&gt;下次新任务再从头解释一遍&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这种方式能完成小任务，但在复杂项目里很容易遇到问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需求没有先拆清楚，AI 直接开始改&lt;/li&gt;
&lt;li&gt;改完代码后缺少系统性 review&lt;/li&gt;
&lt;li&gt;项目规范靠用户反复提醒&lt;/li&gt;
&lt;li&gt;同类错误下次仍然出现&lt;/li&gt;
&lt;li&gt;多个 Agent 工具之间缺少统一工作方法&lt;/li&gt;
&lt;li&gt;经验没有沉淀成可复用规则&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Compound Engineering Plugin&lt;/code&gt; 想解决的就是这类问题。它把 AI 编程拆成多个阶段，让 Agent 不只是执行命令，而是参与一个更完整的工程流程。&lt;/p&gt;
&lt;h2 id=&#34;什么是-compound-engineering&#34;&gt;什么是 Compound Engineering
&lt;/h2&gt;&lt;p&gt;从项目 README 的描述看，Compound Engineering 可以理解为一种 AI 辅助软件开发方法。&lt;/p&gt;
&lt;p&gt;它强调一个循环：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;计划：先理解目标、拆分任务、确认路径&lt;/li&gt;
&lt;li&gt;执行：按计划修改代码、运行命令、处理问题&lt;/li&gt;
&lt;li&gt;评审：检查实现质量、风险和测试覆盖&lt;/li&gt;
&lt;li&gt;学习：把经验沉淀成后续可复用的规则&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这个循环很像真实工程团队的工作方式。&lt;/p&gt;
&lt;p&gt;一个靠谱的工程师不会拿到需求就立刻乱改，也不会改完就直接交差。他会先判断影响范围，再动手实现，之后检查风险和测试结果，最后把踩过的坑记录下来。AI Agent 也需要类似约束。&lt;/p&gt;
&lt;h2 id=&#34;为什么需要插件&#34;&gt;为什么需要插件
&lt;/h2&gt;&lt;p&gt;提示词可以告诉 AI “请先计划再执行”，但提示词本身不一定稳定。&lt;/p&gt;
&lt;p&gt;一旦会话变长、上下文变复杂，模型可能会跳过计划、忽略规则，或者为了完成任务而过度自信。插件的价值在于把流程固化下来，让不同 Agent 环境都能遵循类似方法。&lt;/p&gt;
&lt;p&gt;这类插件通常会把工作流拆成命令、规则、模板或子流程。用户不需要每次手写完整提示词，而是通过固定入口触发某个阶段。&lt;/p&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先让 Agent 生成计划&lt;/li&gt;
&lt;li&gt;再按计划逐步实现&lt;/li&gt;
&lt;li&gt;改完后触发 review&lt;/li&gt;
&lt;li&gt;发现问题后返回修正&lt;/li&gt;
&lt;li&gt;把值得保留的经验写入记忆或规则&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这会让 AI 编程更像“受控协作”，而不是一次性聊天。&lt;/p&gt;
&lt;h2 id=&#34;支持哪些-agent-环境&#34;&gt;支持哪些 Agent 环境
&lt;/h2&gt;&lt;p&gt;README 中提到，项目支持多个 AI 编程环境，包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Claude Code&lt;/li&gt;
&lt;li&gt;Codex&lt;/li&gt;
&lt;li&gt;Cursor&lt;/li&gt;
&lt;li&gt;GitHub Copilot&lt;/li&gt;
&lt;li&gt;Amp&lt;/li&gt;
&lt;li&gt;Factory&lt;/li&gt;
&lt;li&gt;Qwen Code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这点值得注意。&lt;/p&gt;
&lt;p&gt;很多工作流工具只绑定一个客户端，换工具后规则就不能复用。&lt;code&gt;Compound Engineering Plugin&lt;/code&gt; 更像一套跨 Agent 的工程方法，把类似的计划、执行、评审流程带到不同工具里。&lt;/p&gt;
&lt;p&gt;如果你同时使用多个 AI 编程助手，这类统一工作流会更有价值。不同工具能力不同，但项目规范、评审习惯和任务拆解方法应该尽量一致。&lt;/p&gt;
&lt;h2 id=&#34;计划阶段有什么用&#34;&gt;计划阶段有什么用
&lt;/h2&gt;&lt;p&gt;计划阶段的价值，是防止 AI 过早动手。&lt;/p&gt;
&lt;p&gt;复杂任务里，真正重要的问题通常是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;要改哪些文件&lt;/li&gt;
&lt;li&gt;哪些模块可能受影响&lt;/li&gt;
&lt;li&gt;现有模式是什么&lt;/li&gt;
&lt;li&gt;有没有测试&lt;/li&gt;
&lt;li&gt;风险点在哪里&lt;/li&gt;
&lt;li&gt;是否需要先阅读文档&lt;/li&gt;
&lt;li&gt;能不能拆成更小步骤&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果 Agent 没有先想清楚这些问题，就直接开始写代码，很容易做出看似完成、实际偏离项目结构的实现。&lt;/p&gt;
&lt;p&gt;计划并不一定要很长。好的计划应该短、具体、可执行。它的目的不是制造文档，而是让后续实现有边界。&lt;/p&gt;
&lt;h2 id=&#34;执行阶段要避免什么&#34;&gt;执行阶段要避免什么
&lt;/h2&gt;&lt;p&gt;AI 执行代码任务时，最容易出现几类问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;顺手重构无关代码&lt;/li&gt;
&lt;li&gt;覆盖用户已有修改&lt;/li&gt;
&lt;li&gt;只改 happy path&lt;/li&gt;
&lt;li&gt;忽略错误处理&lt;/li&gt;
&lt;li&gt;不按项目已有风格写&lt;/li&gt;
&lt;li&gt;没有运行必要验证&lt;/li&gt;
&lt;li&gt;遇到报错后盲目尝试&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;工作流插件无法保证这些问题完全消失，但可以通过规则和阶段约束减少发生概率。&lt;/p&gt;
&lt;p&gt;比如，执行阶段可以要求 Agent 按计划逐步推进；遇到超出计划范围的发现时，先说明风险；修改共享模块时，补充测试或至少运行相关验证。&lt;/p&gt;
&lt;p&gt;这种约束对大型代码库尤其重要。AI 写代码越快，越需要流程来限制它的惯性。&lt;/p&gt;
&lt;h2 id=&#34;评审阶段为什么重要&#34;&gt;评审阶段为什么重要
&lt;/h2&gt;&lt;p&gt;很多 AI 编程失败，不是因为代码完全不能运行，而是因为细节有问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;边界条件没处理&lt;/li&gt;
&lt;li&gt;状态更新不一致&lt;/li&gt;
&lt;li&gt;API 合约被悄悄改了&lt;/li&gt;
&lt;li&gt;测试覆盖不到关键路径&lt;/li&gt;
&lt;li&gt;错误提示不清楚&lt;/li&gt;
&lt;li&gt;性能或安全风险没有被提到&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;评审阶段就是把 Agent 从“作者模式”切换到“审查模式”。&lt;/p&gt;
&lt;p&gt;作者模式容易为自己的实现找理由；审查模式则要主动找漏洞、回归风险和遗漏测试。把这两个阶段分开，会比让同一个回复里同时完成实现和自我审查更可靠。&lt;/p&gt;
&lt;p&gt;对用户来说，评审输出也更有价值。它能帮助你快速判断这次修改是否值得合并，还是需要继续返工。&lt;/p&gt;
&lt;h2 id=&#34;学习和记忆的意义&#34;&gt;学习和记忆的意义
&lt;/h2&gt;&lt;p&gt;项目名字里的 “Compound” 暗示了一个重要想法：工程经验应该复利增长。&lt;/p&gt;
&lt;p&gt;如果 AI 每次犯错后只是当场修好，下次又犯同样错误，效率提升就很有限。更好的方式是把有价值的经验沉淀下来：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这个项目的目录约定&lt;/li&gt;
&lt;li&gt;某类错误的排查方法&lt;/li&gt;
&lt;li&gt;测试命令和注意事项&lt;/li&gt;
&lt;li&gt;不要触碰的生成文件&lt;/li&gt;
&lt;li&gt;代码风格偏好&lt;/li&gt;
&lt;li&gt;常见实现模式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些经验可以变成规则、记忆、文档或模板。后续任务中，Agent 先读取这些沉淀，再开始工作。&lt;/p&gt;
&lt;p&gt;这就是 AI 编程从“单次问答”走向“长期协作”的关键。&lt;/p&gt;
&lt;h2 id=&#34;适合什么场景&#34;&gt;适合什么场景
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Compound Engineering Plugin&lt;/code&gt; 适合这些场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;长期使用 AI Agent 写代码&lt;/li&gt;
&lt;li&gt;一个项目会被多次、多轮修改&lt;/li&gt;
&lt;li&gt;希望 AI 先计划再实现&lt;/li&gt;
&lt;li&gt;希望改完后自动进入 review 思维&lt;/li&gt;
&lt;li&gt;团队想统一 AI 编程流程&lt;/li&gt;
&lt;li&gt;同时使用 Claude Code、Codex、Cursor 等多个工具&lt;/li&gt;
&lt;li&gt;希望把项目经验沉淀成可复用规则&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果只是偶尔让 AI 写一个小脚本，完整流程可能显得偏重。&lt;/p&gt;
&lt;p&gt;但如果你正在把 AI 编程助手当成日常开发伙伴，计划、执行、评审、学习这套循环就会明显有用。&lt;/p&gt;
&lt;h2 id=&#34;和普通提示词模板有什么区别&#34;&gt;和普通提示词模板有什么区别
&lt;/h2&gt;&lt;p&gt;普通提示词模板通常解决的是“怎么说清楚任务”。&lt;/p&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;请一步步思考&lt;/li&gt;
&lt;li&gt;请先阅读文件&lt;/li&gt;
&lt;li&gt;请保持代码风格一致&lt;/li&gt;
&lt;li&gt;请运行测试&lt;/li&gt;
&lt;li&gt;请总结修改内容&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些提示当然有用，但它们还是依赖用户每次正确使用。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Compound Engineering Plugin&lt;/code&gt; 更偏工作流层。它把这些要求组织成可重复的过程，并适配不同 Agent 工具。这样你不是每次从零写提示词，而是在一套流程里推进任务。&lt;/p&gt;
&lt;p&gt;简单说，提示词模板像提醒，工作流插件像制度。&lt;/p&gt;
&lt;h2 id=&#34;使用时要注意&#34;&gt;使用时要注意
&lt;/h2&gt;&lt;p&gt;第一，不要把流程变成负担。&lt;/p&gt;
&lt;p&gt;小任务不一定需要完整计划和长篇评审。好的工作流应该能根据任务复杂度调整，简单问题快速处理，复杂问题再走完整循环。&lt;/p&gt;
&lt;p&gt;第二，评审不能替代测试。&lt;/p&gt;
&lt;p&gt;Agent review 能发现很多问题，但它仍然可能漏掉真实运行时错误。最终判断还要看测试、类型检查、构建结果和人工审查。&lt;/p&gt;
&lt;p&gt;第三，规则要持续清理。&lt;/p&gt;
&lt;p&gt;沉淀经验很重要，但规则越积越多也会变成噪声。过时规则、重复规则、只适合某次任务的临时经验，都应该定期整理。&lt;/p&gt;
&lt;p&gt;第四，跨工具一致不等于完全相同。&lt;/p&gt;
&lt;p&gt;Claude Code、Codex、Cursor、Copilot 等工具能力和交互方式不同。统一的是工作方法，不一定是每个命令、每个配置细节都完全一样。&lt;/p&gt;
&lt;h2 id=&#34;适合怎样的团队&#34;&gt;适合怎样的团队
&lt;/h2&gt;&lt;p&gt;如果一个团队已经允许 AI Agent 修改真实代码，那么只讨论“哪个模型更强”是不够的。&lt;/p&gt;
&lt;p&gt;更应该关心：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI 修改前是否理解任务&lt;/li&gt;
&lt;li&gt;AI 修改中是否遵守项目边界&lt;/li&gt;
&lt;li&gt;AI 修改后是否主动审查风险&lt;/li&gt;
&lt;li&gt;AI 是否能从历史错误中学习&lt;/li&gt;
&lt;li&gt;团队是否有统一的 Agent 使用规范&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Compound Engineering Plugin&lt;/code&gt; 这类项目的意义就在这里。它把 AI 编程从个人技巧，往团队可复用流程推进了一步。&lt;/p&gt;
&lt;h2 id=&#34;参考&#34;&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/EveryInc/compound-engineering-plugin&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;EveryInc/compound-engineering-plugin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;最后一句&#34;&gt;最后一句
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Compound Engineering Plugin&lt;/code&gt; 值得关注的地方，不是多一个 AI 编程命令，而是把 AI 编程组织成可循环改进的工程流程。&lt;/p&gt;
&lt;p&gt;当 AI Agent 开始参与真实项目，计划、执行、评审和经验沉淀会比单次生成代码更重要。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Codex 开始控制电脑，对以后意味着什么？</title>
        <link>https://knightli.com/2026/04/29/codex-computer-use-update/</link>
        <pubDate>Wed, 29 Apr 2026 11:28:25 +0800</pubDate>
        
        <guid>https://knightli.com/2026/04/29/codex-computer-use-update/</guid>
        <description>&lt;p&gt;Codex 这次最值得关注的变化，不是又多了一个普通按钮，而是它开始往“控制电脑”这个方向走。&lt;/p&gt;
&lt;p&gt;以前我们使用 AI，更多是在聊天框里提问、复制、粘贴、再手动操作软件。&lt;br&gt;
现在这个边界开始往外扩：AI 不只是回答你，而是可以根据你的目标去操作桌面应用。&lt;/p&gt;
&lt;p&gt;这件事短期看是一个新功能，长期看可能会改变很多人使用电脑的方式。&lt;/p&gt;
&lt;h2 id=&#34;这个功能是什么&#34;&gt;这个功能是什么
&lt;/h2&gt;&lt;p&gt;简单说，Codex 的电脑使用能力，就是让它能接触并操作桌面环境。&lt;/p&gt;
&lt;p&gt;它可以做的事包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以选择并控制某个应用&lt;/li&gt;
&lt;li&gt;可以用自然语言下达任务&lt;/li&gt;
&lt;li&gt;可以打开浏览器、AI 工具、本地文件或其他软件&lt;/li&gt;
&lt;li&gt;可以输入内容、点击按钮、等待结果&lt;/li&gt;
&lt;li&gt;可以把多个步骤串成一个任务&lt;/li&gt;
&lt;li&gt;可以在后台继续执行，不需要用户每一步都手动跟着&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它的定位不是单纯替你写一段文本，而是替你完成一段操作流程。&lt;/p&gt;
&lt;p&gt;这就是 Agent 和普通聊天机器人的关键区别：&lt;br&gt;
聊天机器人主要给答案，Agent 更接近“拿到目标后去执行”。&lt;/p&gt;
&lt;h2 id=&#34;为什么这件事重要&#34;&gt;为什么这件事重要
&lt;/h2&gt;&lt;p&gt;过去很多自动化都要求你会写脚本。&lt;/p&gt;
&lt;p&gt;比如你想完成一个跨软件流程：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;打开网页&lt;/li&gt;
&lt;li&gt;找资料&lt;/li&gt;
&lt;li&gt;复制内容&lt;/li&gt;
&lt;li&gt;交给另一个 AI 工具处理&lt;/li&gt;
&lt;li&gt;保存文件&lt;/li&gt;
&lt;li&gt;再打开本地目录检查结果&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果要自动化这件事，传统做法可能是写浏览器脚本、调用 API、写本地程序，甚至还要处理各种软件窗口。&lt;/p&gt;
&lt;p&gt;但很多普通用户不会写这些东西。&lt;br&gt;
就算会写，也未必值得为一个临时任务专门写脚本。&lt;/p&gt;
&lt;p&gt;电脑使用能力的意义就在这里：它把“脚本能力”往自然语言方向推了一步。&lt;/p&gt;
&lt;p&gt;你不一定要告诉它每一步怎么点。&lt;br&gt;
你可以告诉它你要什么结果，让它自己去尝试完成。&lt;/p&gt;
&lt;h2 id=&#34;它能改变哪些工作流&#34;&gt;它能改变哪些工作流
&lt;/h2&gt;&lt;p&gt;我觉得最先被改变的，不会是特别严肃、特别高风险的工作，而是那些“烦、杂、重复、但又不值得专门写程序”的流程。&lt;/p&gt;
&lt;h3 id=&#34;1-跨软件搬运&#34;&gt;1. 跨软件搬运
&lt;/h3&gt;&lt;p&gt;最典型的就是在多个软件之间搬信息。&lt;/p&gt;
&lt;p&gt;以前你可能要在浏览器、文档、聊天窗口、本地文件夹之间来回切。&lt;br&gt;
以后可以把这类任务交给 Agent：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;去找某类资料&lt;/li&gt;
&lt;li&gt;汇总成文档&lt;/li&gt;
&lt;li&gt;保存到指定目录&lt;/li&gt;
&lt;li&gt;打开结果给你确认&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这类工作不难，但很耗注意力。&lt;br&gt;
Agent 的价值就是把这些碎操作吃掉。&lt;/p&gt;
&lt;h3 id=&#34;2-多个-ai-工具协同&#34;&gt;2. 多个 AI 工具协同
&lt;/h3&gt;&lt;p&gt;现在很多人的真实工作流已经不是只用一个 AI。&lt;/p&gt;
&lt;p&gt;可能是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个工具写代码&lt;/li&gt;
&lt;li&gt;一个工具查资料&lt;/li&gt;
&lt;li&gt;一个工具生成图片&lt;/li&gt;
&lt;li&gt;一个工具整理文档&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以前这些工具之间靠人肉复制粘贴。&lt;br&gt;
以后 Agent 可以成为中间层：它负责打开工具、传递上下文、等待输出、整理结果。&lt;/p&gt;
&lt;p&gt;这会让“多个 AI 协同”从手工流程变成半自动流程。&lt;/p&gt;
&lt;h3 id=&#34;3-办公软件自动化&#34;&gt;3. 办公软件自动化
&lt;/h3&gt;&lt;p&gt;表格、PPT、文档、邮件，这些软件都有一个共同特点：功能很强，但很多操作很碎。&lt;/p&gt;
&lt;p&gt;如果 Agent 能稳定控制这些软件，以后的办公自动化门槛会明显下降。&lt;/p&gt;
&lt;p&gt;你不用记菜单在哪里，也不用学复杂快捷键。&lt;br&gt;
你只需要说清楚目标，比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;把这份表格整理成月报&lt;/li&gt;
&lt;li&gt;根据这份文档做一页总结&lt;/li&gt;
&lt;li&gt;把这些资料合并成一个结构清楚的说明&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;真正麻烦的按钮操作，会逐渐被隐藏到自然语言后面。&lt;/p&gt;
&lt;h2 id=&#34;对普通用户意味着什么&#34;&gt;对普通用户意味着什么
&lt;/h2&gt;&lt;p&gt;对普通用户来说，这类功能的影响可能比“模型又聪明了一点”更直接。&lt;/p&gt;
&lt;p&gt;因为它降低的不是知识门槛，而是操作门槛。&lt;/p&gt;
&lt;p&gt;很多人不是不会表达需求，而是不知道软件里该点哪里、怎么组合功能。&lt;br&gt;
Agent 如果能接管这部分，人使用电脑的方式就会变成：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;我描述目标
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Agent 操作软件
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;我检查结果
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这比单纯聊天更接近真实生产力。&lt;/p&gt;
&lt;h2 id=&#34;对软件形态的影响&#34;&gt;对软件形态的影响
&lt;/h2&gt;&lt;p&gt;如果这类 Agent 能力继续成熟，软件本身也会被反向影响。&lt;/p&gt;
&lt;p&gt;过去软件设计主要服务人类点击。&lt;br&gt;
以后软件可能还要服务 Agent 操作。&lt;/p&gt;
&lt;p&gt;这意味着：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;界面元素需要更清晰&lt;/li&gt;
&lt;li&gt;操作反馈需要更稳定&lt;/li&gt;
&lt;li&gt;本地权限需要更细&lt;/li&gt;
&lt;li&gt;软件可能会提供更适合 Agent 调用的接口&lt;/li&gt;
&lt;li&gt;用户会更在意“能不能被 AI 顺利操作”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;长期看，应用之间的边界可能会变薄。&lt;br&gt;
用户关心的不再是“我打开哪个软件”，而是“我要完成什么任务”。&lt;/p&gt;
&lt;h2 id=&#34;现在还不能过度乐观&#34;&gt;现在还不能过度乐观
&lt;/h2&gt;&lt;p&gt;当然，现在还不到完全放手的时候。&lt;/p&gt;
&lt;p&gt;这类能力目前还有几个明显限制：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;稳定性还需要观察&lt;/li&gt;
&lt;li&gt;复杂任务可能中途出错&lt;/li&gt;
&lt;li&gt;权限边界必须谨慎&lt;/li&gt;
&lt;li&gt;涉及账号、支付、删除文件等操作不能随便放权&lt;/li&gt;
&lt;li&gt;额度消耗也不是完全可以忽略&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以现阶段最合适的用法，不是让它完全接管电脑，而是让它处理低风险、可检查、步骤繁琐的任务。&lt;/p&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;整理资料&lt;/li&gt;
&lt;li&gt;生成草稿&lt;/li&gt;
&lt;li&gt;跨工具搬运内容&lt;/li&gt;
&lt;li&gt;打开和检查文件&lt;/li&gt;
&lt;li&gt;做一些可以人工复核的半自动流程&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;最后一句&#34;&gt;最后一句
&lt;/h2&gt;&lt;p&gt;Codex 这次更新真正重要的地方，是它把 AI 从“回答问题”推向了“操作环境”。&lt;/p&gt;
&lt;p&gt;短期看，它是一个电脑使用功能。&lt;br&gt;
长期看，它可能是个人电脑交互方式的一次转向。&lt;/p&gt;
&lt;p&gt;以后我们使用电脑，可能会越来越少地记按钮、找菜单、切窗口。&lt;br&gt;
更多时候，我们只需要说清楚目标，然后让 Agent 去执行，再由人做最后判断。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Codex Skill 明明在目录里，为什么就是不显示？</title>
        <link>https://knightli.com/2026/04/29/codex-skill-not-loaded-because-of-utf-8-bom/</link>
        <pubDate>Wed, 29 Apr 2026 11:18:00 +0800</pubDate>
        
        <guid>https://knightli.com/2026/04/29/codex-skill-not-loaded-because-of-utf-8-bom/</guid>
        <description>&lt;p&gt;这次遇到的问题很隐蔽：&lt;code&gt;~/.codex/skills&lt;/code&gt; 里明明已经放好了多个 skill，新开 Codex 线程之后，侧边栏却还是只能看到少数几个。&lt;/p&gt;
&lt;p&gt;一开始看起来像是缓存或索引问题，但实际原因更具体：几个 &lt;code&gt;SKILL.md&lt;/code&gt; 文件开头带了 UTF-8 BOM，Codex 0.111.0 的 skill loader 没有跳过这个字节，于是误判文件没有合法的 YAML front matter。&lt;/p&gt;
&lt;h2 id=&#34;现象&#34;&gt;现象
&lt;/h2&gt;&lt;p&gt;本地目录里有这些 skill：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;~/.codex/skills/git-commit-push/SKILL.md
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;~/.codex/skills/hugo-rsync-deploy/SKILL.md
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;~/.codex/skills/bilibili-speech-transcriber/SKILL.md
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;~/.codex/skills/product-cutout-normalize/SKILL.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;但新开线程时，实际暴露出来的只有：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bilibili-speech-transcriber
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;product-cutout-normalize
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;也就是说，文件存在不等于当前会话一定能加载成功。Codex 会先解析每个 &lt;code&gt;SKILL.md&lt;/code&gt; 的 front matter，解析失败的 skill 会直接被排除。&lt;/p&gt;
&lt;h2 id=&#34;排查&#34;&gt;排查
&lt;/h2&gt;&lt;p&gt;用 &lt;code&gt;codex exec&lt;/code&gt; 启动一个新会话时，可以看到更直接的错误（在vscode等IDE中可能看不到这些log）：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;failed to load skill C:\Users\knightli\.codex\skills\git-commit-push\SKILL.md: missing YAML frontmatter delimited by ---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;failed to load skill C:\Users\knightli\.codex\skills\hugo-rsync-deploy\SKILL.md: missing YAML frontmatter delimited by ---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这些文件肉眼看起来都有正常的开头：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-md&#34; data-lang=&#34;md&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;name: post-rewrite
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;description: ...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;真正的问题在字节层面。&lt;/p&gt;
&lt;p&gt;失败文件的开头是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;EF-BB-BF-2D-2D-2D
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;能正常加载的文件开头是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2D-2D-2D
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;2D-2D-2D&lt;/code&gt; 就是 &lt;code&gt;---&lt;/code&gt;。前面的 &lt;code&gt;EF-BB-BF&lt;/code&gt; 是 UTF-8 BOM。&lt;/p&gt;
&lt;h2 id=&#34;原因&#34;&gt;原因
&lt;/h2&gt;&lt;p&gt;Codex 0.111.0 的 skill loader 当前要求 &lt;code&gt;SKILL.md&lt;/code&gt; 文件第一个字节就是 &lt;code&gt;---&lt;/code&gt; 的第一个 &lt;code&gt;-&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;如果文件前面带了 UTF-8 BOM，那么文件实际开头就不再是 &lt;code&gt;---&lt;/code&gt;，而是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;BOM + ---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;于是 loader 会认为它没有以 front matter 分隔符开头，最后报：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;missing YAML frontmatter delimited by ---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这不是 skill 内容写错了，也不是目录放错了，而是编码细节让解析器没认出来。&lt;/p&gt;
&lt;h2 id=&#34;修复&#34;&gt;修复
&lt;/h2&gt;&lt;p&gt;把出问题的 &lt;code&gt;SKILL.md&lt;/code&gt; 转成无 BOM 的 UTF-8 即可。&lt;/p&gt;
&lt;p&gt;PowerShell 可以这样处理：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$paths&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;s1&#34;&gt;&amp;#39;C:\Users\knightli\.codex\skills\git-commit-push\SKILL.md&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;s1&#34;&gt;&amp;#39;C:\Users\knightli\.codex\skills\hugo-rsync-deploy\SKILL.md&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$utf8NoBom&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;New-Object&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;Text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;UTF8Encoding&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;$false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;foreach&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$p&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$paths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nv&#34;&gt;$text&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;IO.File&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ReadAllText&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;Text.Encoding&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UTF8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;IO.File&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;WriteAllText&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$utf8NoBom&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;处理后再检查文件头，应该从：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;EF-BB-BF-2D-2D-2D
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;变成：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2D-2D-2D
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;验证&#34;&gt;验证
&lt;/h2&gt;&lt;p&gt;重新启动一个 Codex 会话后，可见 skill 恢复为：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git-commit-push-zh
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;hugo-rsync-deploy
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bilibili-speech-transcriber
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;product-cutout-normalize
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果侧边栏仍然只显示旧的列表，可以退出当前 Codex sidebar 或窗口，再重新打开项目。skill 列表通常在会话启动时加载，中途改文件不一定会立刻刷新到当前线程。&lt;/p&gt;
&lt;h2 id=&#34;最后一句&#34;&gt;最后一句
&lt;/h2&gt;&lt;p&gt;这类问题最容易误判成“Codex 没重新索引”或“skill 没安装好”。&lt;/p&gt;
&lt;p&gt;实际排查时可以先看三件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SKILL.md&lt;/code&gt; 是否真的在正确目录&lt;/li&gt;
&lt;li&gt;文件头部是否有合法的 &lt;code&gt;---&lt;/code&gt; front matter&lt;/li&gt;
&lt;li&gt;文件是否是无 BOM 的 UTF-8&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这次的关键就是第三点：文件看起来没问题，但第一个字节不是 &lt;code&gt;-&lt;/code&gt;，Codex 就没有把它当作一个有效 skill。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Codex 里的 ~/.codex/skills 和 项目/.codex/skills 有什么区别</title>
        <link>https://knightli.com/2026/04/29/difference-between-global-and-project-codex-skills/</link>
        <pubDate>Wed, 29 Apr 2026 11:08:00 +0800</pubDate>
        
        <guid>https://knightli.com/2026/04/29/difference-between-global-and-project-codex-skills/</guid>
        <description>&lt;p&gt;很多人整理 Codex skills 时，最容易卡住的问题就两个：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/.codex/skills&lt;/code&gt; 和 &lt;code&gt;项目/.codex/skills&lt;/code&gt; 有什么区别&lt;/li&gt;
&lt;li&gt;为什么 skill 明明在目录里，当前会话里却不一定显示&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这篇就直接说结论。&lt;/p&gt;
&lt;h2 id=&#34;两者的区别&#34;&gt;两者的区别
&lt;/h2&gt;&lt;p&gt;先记最短版本：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/.codex/skills&lt;/code&gt; 是你的全局技能库&lt;/li&gt;
&lt;li&gt;&lt;code&gt;项目/.codex/skills&lt;/code&gt; 是这个仓库的本地技能库&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;codexskills&#34;&gt;&lt;code&gt;~/.codex/skills&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;适合放：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你自己跨项目反复会用的 skill&lt;/li&gt;
&lt;li&gt;跟具体仓库无关的通用流程&lt;/li&gt;
&lt;li&gt;很明显属于你个人习惯的工作流&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;post-rewrite&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;post-translate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git-commit-push&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hugo-rsync-deploy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bilibili-speech-transcriber&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这类 skill 的特点就是：&lt;strong&gt;离开当前项目也还能用。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;项目codexskills&#34;&gt;&lt;code&gt;项目/.codex/skills&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;适合放：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;只对这个仓库成立的流程&lt;/li&gt;
&lt;li&gt;跟当前项目目录结构、脚本、模板绑定很深的规则&lt;/li&gt;
&lt;li&gt;需要让团队一起共享的 skill&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这个仓库特有的发布流程&lt;/li&gt;
&lt;li&gt;只能在这个项目里用的生成模板&lt;/li&gt;
&lt;li&gt;跟项目私有脚本强绑定的自动化步骤&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这类 skill 的特点是：&lt;strong&gt;离开这个仓库就没意义。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;什么时候放全局什么时候放项目里&#34;&gt;什么时候放全局，什么时候放项目里
&lt;/h2&gt;&lt;p&gt;直接这样判断就够了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;跟你个人习惯有关，放 &lt;code&gt;~/.codex/skills&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;跟仓库规则有关，放 &lt;code&gt;项目/.codex/skills&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;能跨项目复用，优先放全局&lt;/li&gt;
&lt;li&gt;要多人共享、跟仓库一起演进，优先放项目里&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;当前这个仓库是什么情况&#34;&gt;当前这个仓库是什么情况
&lt;/h2&gt;&lt;p&gt;按我现在看到的实际状态：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你的本机里有 &lt;code&gt;~/.codex/skills&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;当前仓库里没有 &lt;code&gt;.codex/skills&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以你现在主要依赖的是全局 skills。&lt;br&gt;
也就是说，像 &lt;code&gt;post-rewrite&lt;/code&gt;、&lt;code&gt;post-translate&lt;/code&gt;、&lt;code&gt;git-commit-push&lt;/code&gt; 这些流程，现在更多是你个人工作流的一部分，不是这个仓库显式自带的一部分。&lt;/p&gt;
&lt;h2 id=&#34;为什么磁盘里有当前会话里却不一定显示&#34;&gt;为什么磁盘里有，当前会话里却不一定显示
&lt;/h2&gt;&lt;p&gt;这里要分清两件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;磁盘存在&lt;/strong&gt;：说明 skill 文件在本地目录里&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;会话暴露&lt;/strong&gt;：说明当前会话把它注册进了可用 skill 列表&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这两者不是一回事。&lt;/p&gt;
&lt;p&gt;所以会出现这种情况：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/.codex/skills&lt;/code&gt; 里已经有 skill&lt;/li&gt;
&lt;li&gt;但 &lt;code&gt;/&lt;/code&gt; 后面的列表里没有显示&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这通常不代表 skill 坏了，更常见的原因是：&lt;strong&gt;当前会话没有把它重新索引进去。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;怎样让-skill-被当前会话暴露&#34;&gt;怎样让 skill 被当前会话暴露
&lt;/h2&gt;&lt;p&gt;最实用的步骤就这几条：&lt;/p&gt;
&lt;h3 id=&#34;1-目录放对&#34;&gt;1. 目录放对
&lt;/h3&gt;&lt;p&gt;全局：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;~/.codex/skills/&amp;lt;skill-name&amp;gt;/SKILL.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;项目级：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;项目/.codex/skills/&amp;lt;skill-name&amp;gt;/SKILL.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;2-skillmd-头部可识别&#34;&gt;2. &lt;code&gt;SKILL.md&lt;/code&gt; 头部可识别
&lt;/h3&gt;&lt;p&gt;最少要有：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-md&#34; data-lang=&#34;md&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;name: your-skill-name
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;description: 这个 skill 是干什么的
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;3-新建或修改后开新会话&#34;&gt;3. 新建或修改后，开新会话
&lt;/h3&gt;&lt;p&gt;很多时候 skill 没显示，不是文件有问题，而是当前会话启动时就已经把可用 skill 列表定下来了。&lt;br&gt;
所以你中途新建 skill，磁盘里虽然已经有了，这次会话也未必会重新认。&lt;/p&gt;
&lt;p&gt;最稳的做法就是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;放好 skill&lt;/li&gt;
&lt;li&gt;结束当前会话&lt;/li&gt;
&lt;li&gt;重新进入项目&lt;/li&gt;
&lt;li&gt;开一个新会话&lt;/li&gt;
&lt;li&gt;再看 &lt;code&gt;/&lt;/code&gt; 里有没有出现&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;4-项目-skill-最好提前放好&#34;&gt;4. 项目 skill 最好提前放好
&lt;/h3&gt;&lt;p&gt;如果你想让 &lt;code&gt;项目/.codex/skills&lt;/code&gt; 更稳定地被识别，最好在进入仓库、启动会话之前，就把这些 skill 放进项目里。&lt;/p&gt;
&lt;h2 id=&#34;最后一句&#34;&gt;最后一句
&lt;/h2&gt;&lt;p&gt;最短结论就是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/.codex/skills&lt;/code&gt; 是你的个人技能库&lt;/li&gt;
&lt;li&gt;&lt;code&gt;项目/.codex/skills&lt;/code&gt; 是仓库的本地规则库&lt;/li&gt;
&lt;li&gt;skill 在目录里，不等于当前会话一定会显示&lt;/li&gt;
&lt;li&gt;想让它显示，最常见的办法就是放对目录、写好 &lt;code&gt;SKILL.md&lt;/code&gt;，然后开新会话&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>OpenAI 发布 GPT-5.5：更强的智能体编码、知识工作与科研能力</title>
        <link>https://knightli.com/2026/04/24/openai-gpt-5-5-release/</link>
        <pubDate>Fri, 24 Apr 2026 08:39:56 +0800</pubDate>
        
        <guid>https://knightli.com/2026/04/24/openai-gpt-5-5-release/</guid>
        <description>&lt;p&gt;OpenAI 在 2026 年 4 月 23 日发布了 &lt;a class=&#34;link&#34; href=&#34;https://openai.com/index/introducing-gpt-5-5/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Introducing GPT-5.5&lt;/a&gt;。从官方页面看，这次更新的重点不是单纯“模型更聪明”，而是更强调模型能不能把复杂任务持续推进下去。&lt;/p&gt;
&lt;p&gt;官方给 GPT-5.5 的定位，是一个更适合真实工作的模型。它不仅要回答问题，还要能写代码、调试、查资料、分析数据、生成文档和表格、操作软件，并在多个工具之间来回切换，直到任务完成。&lt;/p&gt;
&lt;h2 id=&#34;1-gpt-55-主要强在哪里&#34;&gt;1. GPT-5.5 主要强在哪里
&lt;/h2&gt;&lt;p&gt;这次发布页里反复出现的几个方向，可以概括为四类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;智能体编码&lt;/li&gt;
&lt;li&gt;电脑操作与工具使用&lt;/li&gt;
&lt;li&gt;知识工作&lt;/li&gt;
&lt;li&gt;早期科研辅助&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也就是说，GPT-5.5 的重点不是短问短答，而是更长链路的任务。比如一个工程问题不只是“这段代码怎么改”，而是要理解项目结构、定位失败原因、修改相关文件、补测试、验证结果，并尽量减少用户反复提示。&lt;/p&gt;
&lt;p&gt;OpenAI 也特别强调，GPT-5.5 在 Codex 任务中更省 token。这个点很实际，因为编码智能体一旦开始读文件、跑命令、修 bug，token 消耗会非常快。如果模型能用更少的步骤完成同样任务，实际成本和等待时间都会下降。&lt;/p&gt;
&lt;h2 id=&#34;2-编码能力是这次最重要的展示方向&#34;&gt;2. 编码能力是这次最重要的展示方向
&lt;/h2&gt;&lt;p&gt;官方称 GPT-5.5 是目前最强的 agentic coding 模型。&lt;/p&gt;
&lt;p&gt;几个公开指标里，比较值得注意的是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Terminal-Bench 2.0&lt;/code&gt;：GPT-5.5 达到 &lt;code&gt;82.7%&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SWE-Bench Pro&lt;/code&gt;：GPT-5.5 达到 &lt;code&gt;58.6%&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;OpenAI 内部的 &lt;code&gt;Expert-SWE&lt;/code&gt;：GPT-5.5 也高于 GPT-5.4&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些测试的共同点是，它们更接近真实工程流程，而不是只考单个算法题。特别是 Terminal-Bench 这类任务，会涉及命令行操作、规划、试错、工具协调和多步骤验证。&lt;/p&gt;
&lt;p&gt;对日常开发者来说，这里的意义很直接：模型是否能接住更大的任务，取决于它能不能长时间保持上下文、自己检查假设、知道什么时候该跑测试、知道改动会影响哪里。&lt;/p&gt;
&lt;p&gt;GPT-5.5 在 Codex 里的价值，也主要体现在这些地方。它更像是可以接手一段工程任务的协作者，而不是只会补全代码片段的工具。&lt;/p&gt;
&lt;h2 id=&#34;3-知识工作开始变成重点场景&#34;&gt;3. 知识工作开始变成重点场景
&lt;/h2&gt;&lt;p&gt;除了写代码，OpenAI 这次还把 GPT-5.5 放到了更广的办公场景里。&lt;/p&gt;
&lt;p&gt;官方提到，GPT-5.5 在 Codex 中可以更好地生成文档、电子表格和演示文稿，也更适合处理运营研究、表格建模、业务材料整理这类任务。结合电脑操作能力之后，它的目标不是只给建议，而是能直接参与“找资料、理解内容、调用工具、检查输出、整理成结果”这一整条流程。&lt;/p&gt;
&lt;p&gt;发布页里还提到 OpenAI 内部已经在多部门使用 Codex，包括软件工程、财务、传播、市场、数据科学和产品管理等。这里真正值得关注的不是某个单点案例，而是 OpenAI 正在把 Codex 从开发工具扩展为通用工作工具。&lt;/p&gt;
&lt;p&gt;在 ChatGPT 里，GPT-5.5 Thinking 面向 Plus、Pro、Business 和 Enterprise 用户；GPT-5.5 Pro 则面向更难问题和更高准确率需求，提供给 Pro、Business 和 Enterprise 用户。&lt;/p&gt;
&lt;h2 id=&#34;4-科研能力不只是答题更强&#34;&gt;4. 科研能力不只是“答题更强”
&lt;/h2&gt;&lt;p&gt;GPT-5.5 的科研展示也很重。&lt;/p&gt;
&lt;p&gt;官方提到它在遗传学、定量生物学、生物信息学、数学证明等方向都有改进。这里的重点不是模型能不能背出一个知识点，而是能不能处理更接近真实研究的问题：读数据、发现异常、提出分析方式、解释结果，并根据中间结果继续推进。&lt;/p&gt;
&lt;p&gt;发布页里提到的 &lt;code&gt;GeneBench&lt;/code&gt; 和 &lt;code&gt;BixBench&lt;/code&gt;，都更偏多阶段科学分析任务。OpenAI 还提到，一个内部版本的 GPT-5.5 借助自定义工具链，帮助发现了关于 Ramsey numbers 的新证明，并用 Lean 做了验证。&lt;/p&gt;
&lt;p&gt;这类案例还不能简单理解为“AI 已经能独立做科研”，但它说明模型正在从问答工具往研究协作者靠近。尤其是在代码、数据、论文、实验想法混在一起的场景里，GPT-5.5 的长链路推理和工具使用能力会更重要。&lt;/p&gt;
&lt;h2 id=&#34;5-推理效率更强但没有明显变慢&#34;&gt;5. 推理效率：更强但没有明显变慢
&lt;/h2&gt;&lt;p&gt;一个容易被忽略的点是，OpenAI 说 GPT-5.5 在真实服务中的 per-token latency 与 GPT-5.4 相当。&lt;/p&gt;
&lt;p&gt;通常更大的模型、更强的模型会带来更高延迟。OpenAI 这次强调，它们通过推理系统优化，让 GPT-5.5 在智能提升的同时保持速度。发布页里还提到，Codex 分析生产流量模式并编写负载分配相关启发式算法，使 token 生成速度提升超过 &lt;code&gt;20%&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;这个细节很有意思：模型不仅被基础设施服务，也反过来帮助改进服务它的基础设施。&lt;/p&gt;
&lt;h2 id=&#34;6-安全策略会更严格尤其是网络安全方向&#34;&gt;6. 安全策略会更严格，尤其是网络安全方向
&lt;/h2&gt;&lt;p&gt;GPT-5.5 的网络安全能力更强，所以 OpenAI 同时加强了安全限制。&lt;/p&gt;
&lt;p&gt;官方说明中提到，GPT-5.5 在网络安全能力上比 GPT-5.4 有提升，因此会部署更严格的分类器，尤其针对高风险活动、敏感网络安全请求和重复滥用行为。&lt;/p&gt;
&lt;p&gt;这意味着一部分用户在使用网络安全相关能力时，可能会遇到更多拒答或限制。OpenAI 也提供了 Trusted Access for Cyber，用于让经过验证的防御性用户获得更少不必要阻碍。&lt;/p&gt;
&lt;p&gt;对普通开发者来说，可以简单理解为：合法的安全加固、漏洞修复、代码审计会继续被支持，但高风险攻击链路会被更严格地控制。&lt;/p&gt;
&lt;h2 id=&#34;7-可用性与-api-价格&#34;&gt;7. 可用性与 API 价格
&lt;/h2&gt;&lt;p&gt;根据 OpenAI 发布页，GPT-5.5 的可用性如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ChatGPT：GPT-5.5 Thinking 面向 Plus、Pro、Business、Enterprise 用户&lt;/li&gt;
&lt;li&gt;ChatGPT：GPT-5.5 Pro 面向 Pro、Business、Enterprise 用户&lt;/li&gt;
&lt;li&gt;Codex：GPT-5.5 面向 Plus、Pro、Business、Enterprise、Edu、Go 计划&lt;/li&gt;
&lt;li&gt;Codex：上下文窗口为 &lt;code&gt;400K&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Codex Fast mode：生成速度约 &lt;code&gt;1.5x&lt;/code&gt;，成本为 &lt;code&gt;2.5x&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;API 方面，OpenAI 表示 &lt;code&gt;gpt-5.5&lt;/code&gt; 和 &lt;code&gt;gpt-5.5-pro&lt;/code&gt; 会很快开放。&lt;/p&gt;
&lt;p&gt;官方给出的 API 价格是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gpt-5.5&lt;/code&gt;：输入 &lt;code&gt;5 美元 / 1M tokens&lt;/code&gt;，输出 &lt;code&gt;30 美元 / 1M tokens&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gpt-5.5-pro&lt;/code&gt;：输入 &lt;code&gt;30 美元 / 1M tokens&lt;/code&gt;，输出 &lt;code&gt;180 美元 / 1M tokens&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gpt-5.5&lt;/code&gt; API 上下文窗口为 &lt;code&gt;1M&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Batch 和 Flex 为标准 API 价格的一半&lt;/li&gt;
&lt;li&gt;Priority processing 为标准价格的 &lt;code&gt;2.5x&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这个价格明显高于很多日常模型，所以它更适合高价值任务：复杂工程改造、长文档分析、自动化办公、科研辅助、重要业务流程，而不是普通闲聊。&lt;/p&gt;
&lt;h2 id=&#34;8-怎么看这次发布&#34;&gt;8. 怎么看这次发布
&lt;/h2&gt;&lt;p&gt;如果只看一句话，GPT-5.5 的重点是：OpenAI 正在把模型从“回答问题”继续推向“完成工作”。&lt;/p&gt;
&lt;p&gt;它最值得关注的地方，不只是 benchmark 分数提升，而是几种能力开始汇合：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;更强的长任务保持能力&lt;/li&gt;
&lt;li&gt;更稳定的工具使用&lt;/li&gt;
&lt;li&gt;更好的工程上下文理解&lt;/li&gt;
&lt;li&gt;更适合文档、表格、研究和业务流程&lt;/li&gt;
&lt;li&gt;更长上下文和更高 token 效率&lt;/li&gt;
&lt;li&gt;更严格的高风险能力控制&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对开发者来说，最值得试的是 Codex 里的复杂工程任务。对企业用户来说，更值得关注的是它能不能把一部分跨工具、跨文档、跨流程的工作变成可交付结果。&lt;/p&gt;
&lt;p&gt;GPT-5.5 不是一次只面向聊天体验的小更新，而更像是 OpenAI 在继续推进“AI 作为工作执行层”的方向。&lt;/p&gt;
&lt;h2 id=&#34;相关链接&#34;&gt;相关链接
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://openai.com/index/introducing-gpt-5-5/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Introducing GPT-5.5 - OpenAI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>ChatGPT Codex 配额使用情况查询面板：codex-quota的使用方法</title>
        <link>https://knightli.com/2026/04/16/codex-quota-cli-web-docker-guide/</link>
        <pubDate>Thu, 16 Apr 2026 18:13:04 +0800</pubDate>
        
        <guid>https://knightli.com/2026/04/16/codex-quota-cli-web-docker-guide/</guid>
        <description>&lt;h2 id=&#34;这个项目做什么&#34;&gt;这个项目做什么
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;codex-quota&lt;/code&gt; 是一个轻量工具，能查询 ChatGPT Codex 配额使用情况，数据来源是 &lt;code&gt;https://chatgpt.com/backend-api/wham/usage&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;主要功能：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;支持单账号或多账号（&lt;code&gt;account/*.auth.json&lt;/code&gt;）查询。&lt;/li&gt;
&lt;li&gt;输出 &lt;code&gt;five_hour%&lt;/code&gt;、&lt;code&gt;weekly%&lt;/code&gt;、&lt;code&gt;weekly_reset&lt;/code&gt;，并标记来源（&lt;code&gt;network&lt;/code&gt; 或 &lt;code&gt;cache&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;对临时失败（&lt;code&gt;408&lt;/code&gt;、&lt;code&gt;429&lt;/code&gt;、&lt;code&gt;5xx&lt;/code&gt;）做指数退避重试。&lt;/li&gt;
&lt;li&gt;内置本地缓存，减少已耗尽配额时的重复请求。&lt;/li&gt;
&lt;li&gt;提供 Web Dashboard、JSON API、auth 文件管理页面。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;优点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;轻量：单脚本可跑，依赖简单。&lt;/li&gt;
&lt;li&gt;实用：CLI 和 Web 两种入口都能用。&lt;/li&gt;
&lt;li&gt;可部署：支持 Docker 和 Docker Compose。&lt;/li&gt;
&lt;li&gt;易运维：支持重试、缓存和定时刷新。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;先准备好账号凭证&#34;&gt;先准备好账号凭证
&lt;/h2&gt;&lt;p&gt;在 &lt;code&gt;account/&amp;lt;name&amp;gt;.auth.json&lt;/code&gt; 创建凭证文件，例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;tokens&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;access_token&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;eyJ...&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;account_id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;user-xxxxxxxx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;解释：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;access_token&lt;/code&gt; 和 &lt;code&gt;account_id&lt;/code&gt; 是查询接口所需字段。&lt;/li&gt;
&lt;li&gt;文件名里的 &lt;code&gt;&amp;lt;name&amp;gt;&lt;/code&gt; 会作为账号名显示在结果中。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;本地-cli-用法保留原命令&#34;&gt;本地 CLI 用法（保留原命令）
&lt;/h2&gt;&lt;p&gt;安装依赖：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install -r requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;解释：安装项目运行依赖。&lt;/p&gt;
&lt;p&gt;查询全部账号：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python codex_quota.py
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;解释：读取 &lt;code&gt;account/*.auth.json&lt;/code&gt;，汇总输出所有账号配额。&lt;/p&gt;
&lt;p&gt;查询单个账号：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python codex_quota.py your_account_name
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;解释：只查询 &lt;code&gt;account/your_account_name.auth.json&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;强制刷新（跳过缓存）：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python codex_quota.py --refresh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;解释：忽略本地缓存，直接请求最新接口数据。&lt;/p&gt;
&lt;h2 id=&#34;cli-参数说明readme-对齐&#34;&gt;CLI 参数说明（README 对齐）
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;account_name&lt;/code&gt;：可选账号名（不带 &lt;code&gt;.auth.json&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--account-dir&lt;/code&gt;：凭证目录，默认 &lt;code&gt;account&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--chatgpt-url&lt;/code&gt;：配额接口地址。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--raw-json&lt;/code&gt;：输出完整 JSON 响应体。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--raw-headers&lt;/code&gt;：输出响应头。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--refresh&lt;/code&gt;：忽略缓存。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--retries&lt;/code&gt;：重试次数，默认 &lt;code&gt;3&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--retry-delay&lt;/code&gt;：基础重试间隔秒数，默认 &lt;code&gt;2.0&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;web-dashboard-用法保留原命令&#34;&gt;Web Dashboard 用法（保留原命令）
&lt;/h2&gt;&lt;p&gt;启动服务：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python codex_quota_service.py --host 0.0.0.0 --port &lt;span class=&#34;m&#34;&gt;8081&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;解释：启动 HTTP 服务并监听 &lt;code&gt;8081&lt;/code&gt; 端口。&lt;/p&gt;
&lt;p&gt;访问地址：&lt;code&gt;http://localhost:8081&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Service 参数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--host&lt;/code&gt;：监听地址，默认 &lt;code&gt;0.0.0.0&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--port&lt;/code&gt;：端口，默认 &lt;code&gt;8081&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--interval-seconds&lt;/code&gt;：调度刷新间隔，默认 &lt;code&gt;3600&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--account-dir&lt;/code&gt;：凭证目录，默认 &lt;code&gt;account&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--state-file&lt;/code&gt;：状态文件路径，默认 &lt;code&gt;&amp;lt;account-dir&amp;gt;/codex_quota_web_results.json&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--account-name&lt;/code&gt;：可选，单账号模式。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--chatgpt-url&lt;/code&gt;：配额接口地址。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--retries&lt;/code&gt;：重试次数。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--retry-delay&lt;/code&gt;：基础重试延迟。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--refresh&lt;/code&gt;：调度刷新时忽略 CLI 缓存。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;http-接口方便接自动化&#34;&gt;HTTP 接口（方便接自动化）
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /&lt;/code&gt;：Dashboard 页面。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/results&lt;/code&gt;：最新结果 JSON。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /refresh&lt;/code&gt;：立即刷新并跳回 &lt;code&gt;/&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /auth&lt;/code&gt;：列出 auth 文件。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /auth/new&lt;/code&gt;：新建 auth 文件表单。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /auth/edit?name=&amp;lt;account&amp;gt;&lt;/code&gt;：编辑 auth 文件表单。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /auth/save&lt;/code&gt;：创建/更新 auth 文件。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /auth/delete&lt;/code&gt;：删除 auth 文件。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;docker-用法保留原命令&#34;&gt;Docker 用法（保留原命令）
&lt;/h2&gt;&lt;p&gt;构建镜像：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker build -t codex-quota .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;解释：把当前项目打包成 &lt;code&gt;codex-quota&lt;/code&gt; 镜像。&lt;/p&gt;
&lt;p&gt;运行容器（映射 8081）：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker run --rm -p 8081:8081 -v ./account:/app/account codex-quota
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;解释：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--rm&lt;/code&gt;：容器退出自动删除。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-p 8081:8081&lt;/code&gt;：主机端口映射到容器端口。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-v ./account:/app/account&lt;/code&gt;：把本地凭证目录挂载进容器。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;访问地址：&lt;code&gt;http://localhost:8081&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;docker-compose-用法保留原命令&#34;&gt;Docker Compose 用法（保留原命令）
&lt;/h2&gt;&lt;p&gt;启动：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose up --build
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;解释：按 &lt;code&gt;docker-compose.yml&lt;/code&gt; 构建并启动服务。&lt;/p&gt;
&lt;p&gt;访问地址：&lt;code&gt;http://localhost:8081&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;使用建议&#34;&gt;使用建议
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;多账号场景优先走 Dashboard，便于统一查看和管理 auth 文件。&lt;/li&gt;
&lt;li&gt;告警或自动化集成优先用 &lt;code&gt;GET /api/results&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;公开仓库不要提交真实 &lt;code&gt;access_token&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;如果你看到大量临时错误，可调大 &lt;code&gt;--retries&lt;/code&gt; 与 &lt;code&gt;--retry-delay&lt;/code&gt;。&lt;/li&gt;
&lt;/ol&gt;
</description>
        </item>
        <item>
        <title>Codex 额度怎么算：5 小时限额、周限额和 Credit 消耗</title>
        <link>https://knightli.com/2026/04/15/codex-usage-limits-five-hour-weekly-credits/</link>
        <pubDate>Wed, 15 Apr 2026 22:50:00 +0800</pubDate>
        
        <guid>https://knightli.com/2026/04/15/codex-usage-limits-five-hour-weekly-credits/</guid>
        <description>&lt;p&gt;很多人第一次看 Codex 额度时，会以为 &lt;code&gt;5 小时限额&lt;/code&gt; 是一个短期余额池，只有它用完之后才开始扣 &lt;code&gt;周限额&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;实际不是这样。Codex 更像是同时检查多个额度窗口：短窗口防止短时间爆量，周窗口限制一周总量。一次 Codex 使用通常会同时计入这两个窗口。&lt;/p&gt;
&lt;p&gt;所以你看到：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5 小时额度还剩很多
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;但 weekly 额度已经下降
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;通常是正常现象。&lt;/p&gt;
&lt;h2 id=&#34;01-先记住结论&#34;&gt;01 先记住结论
&lt;/h2&gt;&lt;p&gt;Codex 额度可以先按下面三句话理解：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;5 小时限额&lt;/code&gt; 和 &lt;code&gt;周限额&lt;/code&gt; 是同时生效，不是先后扣除。&lt;/li&gt;
&lt;li&gt;周限额用完后，即使 5 小时额度还有，通常也不能继续用同一个订阅额度池。&lt;/li&gt;
&lt;li&gt;Codex 不是简单按消息条数计费，而是和模型、tokens、任务复杂度、上下文、执行位置有关。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;用伪代码表示就是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;can_use_codex =
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    five_hour_remaining &amp;gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &amp;amp;&amp;amp; weekly_remaining &amp;gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &amp;amp;&amp;amp; 没有触发其它产品策略限制
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;5 小时窗口重置，只恢复 5 小时额度；不会恢复 weekly 额度。weekly 额度要等自己的 reset，或者在支持的计划里购买额外 credits。&lt;/p&gt;
&lt;h2 id=&#34;02-为什么会同时扣两个窗口&#34;&gt;02 为什么会同时扣两个窗口
&lt;/h2&gt;&lt;p&gt;可以把 Codex 的额度想成两个闸门：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;窗口&lt;/th&gt;
          &lt;th&gt;作用&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;5 小时窗口&lt;/td&gt;
          &lt;td&gt;防止短时间高频使用&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;周窗口&lt;/td&gt;
          &lt;td&gt;控制一周总使用量&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;每次 Codex 任务都会产生一次实际消耗。这个消耗会反映到当前相关的 rate limit 窗口里。&lt;/p&gt;
&lt;p&gt;因此不是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;先扣 5 小时额度
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5 小时额度用完后
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;再扣周额度
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;而更像是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;一次 Codex 请求
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;=&amp;gt; 计入 5 小时窗口
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;=&amp;gt; 同时计入周窗口
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这就是“5 小时额度没用完，但 weekly 也在下降”的核心原因。&lt;/p&gt;
&lt;h2 id=&#34;03-当前更应该看-token-based-credits&#34;&gt;03 当前更应该看 token-based credits
&lt;/h2&gt;&lt;p&gt;OpenAI 没有公开一个用户可以完全复算的 Codex 扣费公式。官方公开的是 rate card、影响因素和不同模型的 credit 单价。&lt;/p&gt;
&lt;p&gt;截至 2026-04-15，Codex rate card 的主口径已经是 &lt;code&gt;token-based credits&lt;/code&gt;。也就是根据输入 tokens、缓存输入 tokens、输出 tokens 折算 credits。&lt;/p&gt;
&lt;p&gt;官方给出的示例价格如下：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;模型&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;输入 / 1M tokens&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;缓存输入 / 1M tokens&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;输出 / 1M tokens&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;GPT-5.4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;62.50 credits&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;6.250 credits&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;375 credits&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;GPT-5.4-Mini&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;18.75 credits&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;1.875 credits&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;113 credits&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;GPT-5.3-Codex&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;43.75 credits&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4.375 credits&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;350 credits&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;GPT-5.2-Codex&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;43.75 credits&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4.375 credits&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;350 credits&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;GPT-5.1-Codex-Max&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;31.25 credits&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;3.125 credits&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;250 credits&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;GPT-5.1-Codex-mini&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;6.25 credits&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;0.625 credits&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;50 credits&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;所以一个粗略估算公式是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;本次消耗
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;≈ 输入 tokens / 1,000,000 × 模型输入单价
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;+ 缓存输入 tokens / 1,000,000 × 模型缓存输入单价
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;+ 输出 tokens / 1,000,000 × 模型输出单价
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这不是精确账单公式，但足够解释趋势：输出很贵，长上下文很贵，高能力模型更贵。官方还说明 &lt;code&gt;Fast mode&lt;/code&gt; 会消耗 2 倍 credits，&lt;code&gt;Code review&lt;/code&gt; 使用 GPT-5.3-Codex 的价格。&lt;/p&gt;
&lt;h2 id=&#34;04-不要再只看消息条数&#34;&gt;04 不要再只看“消息条数”
&lt;/h2&gt;&lt;p&gt;同样发 10 次 Codex，消耗可能完全不同。&lt;/p&gt;
&lt;p&gt;轻量任务通常更省：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;改一个小函数&lt;/li&gt;
&lt;li&gt;解释一段短代码&lt;/li&gt;
&lt;li&gt;写一小段文案&lt;/li&gt;
&lt;li&gt;在明确文件里做局部修改&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;重任务会更贵：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;扫描大型代码库&lt;/li&gt;
&lt;li&gt;长时间运行 agent&lt;/li&gt;
&lt;li&gt;多轮读取、编辑、测试、修复&lt;/li&gt;
&lt;li&gt;生成大量代码或长报告&lt;/li&gt;
&lt;li&gt;使用 cloud task&lt;/li&gt;
&lt;li&gt;开启 fast mode&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此，&lt;code&gt;消息数量&lt;/code&gt; 只能作为很粗的感觉，不能用来判断真实消耗。&lt;/p&gt;
&lt;h2 id=&#34;05-local-task-和-cloud-task-的差别&#34;&gt;05 local task 和 cloud task 的差别
&lt;/h2&gt;&lt;p&gt;Codex 里很容易拉开消耗差距的是执行位置。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;local task&lt;/code&gt; 更像是在你的本地工作区里读文件、改代码、跑命令。&lt;code&gt;cloud task&lt;/code&gt; 则把任务交给云端环境托管执行，适合更长、更自动化的流程。&lt;/p&gt;
&lt;p&gt;从额度角度看，cloud task 往往更贵。原因也很直接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需要云端执行环境&lt;/li&gt;
&lt;li&gt;任务通常更长&lt;/li&gt;
&lt;li&gt;工具调用更多&lt;/li&gt;
&lt;li&gt;上下文更大&lt;/li&gt;
&lt;li&gt;自动化链路更完整&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果只是普通代码编辑、文章整理、局部修复，优先 local task 会更省。cloud task 更适合确实需要云端托管的任务。&lt;/p&gt;
&lt;h2 id=&#34;06-为什么-weekly-掉得特别快&#34;&gt;06 为什么 weekly 掉得特别快
&lt;/h2&gt;&lt;p&gt;如果你觉得“5 小时额度没怎么动，但 weekly 掉很多”，常见原因有这些：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用了 cloud task。&lt;/li&gt;
&lt;li&gt;使用了更贵的模型。&lt;/li&gt;
&lt;li&gt;开启了 fast mode。&lt;/li&gt;
&lt;li&gt;上下文很大，Codex 读了很多文件或保留了很长对话。&lt;/li&gt;
&lt;li&gt;输出很长，比如大量代码、长报告、长日志分析。&lt;/li&gt;
&lt;li&gt;任务链很长，比如搜索、编辑、测试、修复、再测试。&lt;/li&gt;
&lt;li&gt;自己的额度脚本把窗口标签解析错了。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果你是用脚本读 &lt;code&gt;/backend-api/wham/usage&lt;/code&gt; 之类的字段，不要只看加工后的 &lt;code&gt;five_hour%&lt;/code&gt;、&lt;code&gt;weekly%&lt;/code&gt;。最好先看 raw JSON 里的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;limit_window_seconds&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;percent_left&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;reset_at&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;bucket / feature 名称&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;常见窗口长度可以这样判断：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;limit_window_seconds = 18000
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;=&amp;gt; 约 5 小时窗口
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;limit_window_seconds = 604800
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;=&amp;gt; 约 7 天窗口
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果脚本把两个窗口标反，就会误判额度变化。&lt;/p&gt;
&lt;h2 id=&#34;07-更省额度的使用方式&#34;&gt;07 更省额度的使用方式
&lt;/h2&gt;&lt;p&gt;想让 weekly 撑得久一点，可以这样用：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;把大任务拆成小任务。先处理一个文件、一个 bug、一个功能点。&lt;/li&gt;
&lt;li&gt;能 local 就 local，谨慎使用 cloud task。&lt;/li&gt;
&lt;li&gt;明确告诉 Codex 相关路径，减少无关扫描。&lt;/li&gt;
&lt;li&gt;避免一次塞入巨大日志、长文件、无关上下文。&lt;/li&gt;
&lt;li&gt;轻量任务可以用更便宜的 mini 模型。&lt;/li&gt;
&lt;li&gt;长任务前先让 Codex 出计划，再进入执行。&lt;/li&gt;
&lt;li&gt;不需要长报告时，明确要求“简短回答”。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最实用的记忆方式是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;是否能继续用
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;= 短窗口还有额度
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;amp;&amp;amp; 周窗口还有额度
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;消耗快不快
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;= 模型价格
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;× tokens
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;× 输出长度
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;× 任务复杂度
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;× 执行位置
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个模型不能精确对账，但足够解释大多数 Codex 额度现象。&lt;/p&gt;
&lt;h2 id=&#34;相关链接&#34;&gt;相关链接
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/11369540-using-codex-with-your-chatgpt-plan&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Using Codex with your ChatGPT plan - OpenAI Help Center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/11481834&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;ChatGPT Rate Card - OpenAI Help Center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/zh-hans-cn/articles/20001106-codex-rate-card&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Codex rate card - OpenAI Help Center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/12642688-using-credits-for-flexible-usage-in-chatgpt-pluspro&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Using Credits for Flexible Usage in ChatGPT - OpenAI Help Center&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Codex 额度用量统计</title>
        <link>https://knightli.com/2026/04/12/codex-usage-quota-check/</link>
        <pubDate>Sun, 12 Apr 2026 00:01:33 +0800</pubDate>
        
        <guid>https://knightli.com/2026/04/12/codex-usage-quota-check/</guid>
        <description>&lt;p&gt;如果你想查看 Codex 当前账号的额度剩余情况，可以直接写一个小脚本去请求 ChatGPT 的 &lt;code&gt;/backend-api/wham/usage&lt;/code&gt; 接口。&lt;/p&gt;
&lt;p&gt;这类脚本的思路很简单：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;从 &lt;code&gt;auth.json&lt;/code&gt; 里读取 &lt;code&gt;tokens.access_token&lt;/code&gt; 和 &lt;code&gt;tokens.account_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;请求 &lt;code&gt;https://chatgpt.com/backend-api/wham/usage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;在请求头里带上 &lt;code&gt;Authorization: Bearer ...&lt;/code&gt; 和 &lt;code&gt;ChatGPT-Account-Id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;解析返回结果里的五小时窗口和周窗口额度&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;适合做什么&#34;&gt;适合做什么
&lt;/h2&gt;&lt;p&gt;这个方法适合你在本地快速确认：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;五小时额度还剩多少&lt;/li&gt;
&lt;li&gt;周额度还剩多少&lt;/li&gt;
&lt;li&gt;额度会在什么时候重置&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你有多个账号，也可以让脚本批量读取 &lt;code&gt;account/*.auth.json&lt;/code&gt;，统一输出一张摘要表。
auth.json文件可以从 ~/.codex/ 目录下找到, 对应你当前登录的chatgpt账户。&lt;/p&gt;
&lt;h2 id=&#34;最关键的输入&#34;&gt;最关键的输入
&lt;/h2&gt;&lt;p&gt;脚本通常只依赖两项凭证：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;access_token&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;account_id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它们一般都可以从本地 &lt;code&gt;auth.json&lt;/code&gt; 中拿到。只要这两个值有效，请求头就能按下面的形式组织：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;headers&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;Authorization&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Bearer &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;auth_token&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;Accept&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;ChatGPT-Account-Id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_account_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;Origin&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://chatgpt.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;Referer&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://chatgpt.com/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;User-Agent&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Mozilla/5.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;返回结果怎么看&#34;&gt;返回结果怎么看
&lt;/h2&gt;&lt;p&gt;接口返回后，重点看的是两类窗口：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;five_hour&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;weekly&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;脚本可以把它们统一整理成下面几项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;剩余额度百分比&lt;/li&gt;
&lt;li&gt;重置时间&lt;/li&gt;
&lt;li&gt;对应的时间窗口长度&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果接口字段名有差异，也可以顺手兼容 &lt;code&gt;primary_window&lt;/code&gt;、&lt;code&gt;secondary_window&lt;/code&gt;、&lt;code&gt;five_hour_limit&lt;/code&gt;、&lt;code&gt;weekly_limit&lt;/code&gt; 这些变体。&lt;/p&gt;
&lt;h2 id=&#34;常见问题&#34;&gt;常见问题
&lt;/h2&gt;&lt;p&gt;如果脚本返回 401，通常说明 &lt;code&gt;access_token&lt;/code&gt; 已过期或无效。&lt;/p&gt;
&lt;p&gt;如果返回 403，通常说明当前账号没有权限访问这个接口，或者账号状态异常。&lt;/p&gt;
&lt;p&gt;如果你看到同一个响应里字段命名不一致，也不用太意外。实际处理时最好把不同命名方式统一映射后再输出。&lt;/p&gt;
&lt;h2 id=&#34;参考链接&#34;&gt;参考链接
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;codex-auth-manager&lt;/code&gt;：&lt;a class=&#34;link&#34; href=&#34;https://github.com/RioArisk/codex-auth-manager&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/RioArisk/codex-auth-manager&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;代码&#34;&gt;代码
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;  1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;  9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 71
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 72
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 73
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 74
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 75
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 76
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 77
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 78
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 79
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 80
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 81
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 82
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 83
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 84
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 85
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 86
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 87
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 88
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 89
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 90
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 91
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 92
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 93
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 94
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 95
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 96
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 97
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 98
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 99
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;100
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;101
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;102
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;103
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;104
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;105
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;106
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;107
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;108
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;109
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;110
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;111
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;112
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;113
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;114
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;115
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;116
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;117
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;118
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;119
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;120
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;121
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;122
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;123
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;124
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;125
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;126
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;127
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;128
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;129
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;130
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;131
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;132
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;133
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;134
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;135
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;136
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;137
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;138
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;139
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;140
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;141
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;142
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;143
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;144
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;145
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;146
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;147
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;148
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;149
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;150
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;151
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;152
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;153
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;154
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;155
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;156
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;157
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;158
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;159
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;160
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;161
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;162
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;163
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;164
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;165
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;166
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;167
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;168
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;169
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;170
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;171
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;172
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;173
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;174
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;175
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;176
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;177
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;178
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;179
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;180
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;181
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;182
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;183
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;184
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;185
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;186
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;187
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;188
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;189
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;190
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;191
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;192
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;193
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;194
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;195
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;196
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;197
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;198
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;199
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;200
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;201
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;202
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;203
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;204
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;205
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;206
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;207
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;208
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;209
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;210
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;211
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;212
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;213
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;214
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;215
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;216
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;217
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;218
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;219
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;220
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;221
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;222
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;223
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;224
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;225
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;226
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;227
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;228
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;229
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;230
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;231
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;232
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;233
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;234
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;235
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;236
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;237
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;238
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;239
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;240
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;241
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;242
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;243
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;244
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;245
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;246
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;247
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;248
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;249
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;250
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;251
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;252
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;253
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;254
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;255
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;256
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;257
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;258
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;259
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;260
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;261
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;262
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;263
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;264
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;265
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;266
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;267
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;268
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;269
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;270
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;271
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;272
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;273
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;274
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;275
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;276
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;277
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;278
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;279
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;280
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;281
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;282
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;283
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;284
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;285
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;286
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;287
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;288
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;289
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;290
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;291
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;292
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;293
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;294
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;295
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;296
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;297
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;298
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;299
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;300
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;301
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;302
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;303
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;304
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;305
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;306
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;307
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;308
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;309
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;310
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;311
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;312
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;313
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;314
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;315
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;316
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;317
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;318
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;319
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;320
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;321
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;322
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;323
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;324
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;325
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;326
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;327
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;328
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;329
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;330
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;331
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;332
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;333
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;334
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;335
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;336
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;337
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;338
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;339
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;340
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;341
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;342
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;343
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;344
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;345
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;346
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;347
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;348
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;349
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;350
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;351
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;352
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;353
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;354
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;355
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;356
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;357
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;358
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;359
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;360
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;361
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;362
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;363
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;364
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;365
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;366
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;367
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;368
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;369
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;370
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;371
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;372
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;373
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;374
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;375
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;376
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;377
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;378
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;379
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;380
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;381
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;382
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;383
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;384
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;385
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;386
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;387
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;388
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;389
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;390
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;391
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;392
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;393
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;394
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;395
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;396
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;397
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;398
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;399
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;400
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;401
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;402
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;403
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;404
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;405
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;406
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;407
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;408
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;409
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;410
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;411
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;412
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;413
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;414
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;415
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;416
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;417
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;418
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;419
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;420
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;421
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;422
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;423
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;424
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;425
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;426
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;427
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;428
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;429
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;430
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;431
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;432
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;433
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;434
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;435
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;436
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;437
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;438
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;439
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;440
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;441
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;442
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;443
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;444
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;445
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;446
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;447
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;448
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;449
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;450
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;451
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;452
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;453
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;454
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;455
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;456
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;457
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;458
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;459
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;460
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;argparse&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;base64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;datetime&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timedelta&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timezone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pathlib&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;typing&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Any&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;UTC&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timezone&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;utc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;CST&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timezone&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;timedelta&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hours&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;CST&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;parse_args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;argparse&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Namespace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;argparse&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Query ChatGPT Codex usage from /backend-api/wham/usage.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;account_name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;nargs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;?&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;help&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Account name used to load account/&amp;lt;account_name&amp;gt;.auth.json. If omitted, load all *.auth.json files in account/.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;--account-dir&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;account&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;help&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Directory containing &amp;lt;account_name&amp;gt;.auth.json files.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;--chatgpt-url&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;https://chatgpt.com/backend-api/wham/usage&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;help&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ChatGPT usage endpoint.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;--raw-json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;action&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;store_true&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;help&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Print the full JSON response body.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_argument&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;--raw-headers&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;action&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;store_true&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;help&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Print response headers.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parser&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parse_args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;print_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dumps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;indent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ensure_ascii&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;load_auth_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;path_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;path&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;expanduser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;loads&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;encoding&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;utf-8&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;ne&#34;&gt;OSError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;JSONDecodeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_nested_string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;keys&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;current&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Any&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;keys&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;current&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;current&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;current&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;current&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;current&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;current&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;format_dt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dt&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;astimezone&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;strftime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;%Y-%m-&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%d&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; %H:%M:%S %Z&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;format_cst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format_dt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;epoch_ms_to_dt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;raw&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;ne&#34;&gt;TypeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;ValueError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Newer responses sometimes use epoch seconds, older ones use epoch milliseconds.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;timestamp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;raw&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;raw&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;11&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;raw&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fromtimestamp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;timestamp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tz&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UTC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;first_dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;keys&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;keys&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;decode_jwt_exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;token&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;payload&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;payload&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;=&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;payload&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;loads&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;base64&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;urlsafe_b64decode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;payload&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;encode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ascii&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;exp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;exp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exp&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fromtimestamp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tz&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UTC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;ne&#34;&gt;ValueError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;TypeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;JSONDecodeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_percent_left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;percent_left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;percent_left&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;percent_left&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;percent_left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;remaining_percent&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;percent_left&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;percent_left&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;used_percent&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;used_percent&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;used_percent&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;used_percent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;ne&#34;&gt;TypeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;ValueError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;resolve_limit_window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;reset_at&amp;#34;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;reset_time_ms&amp;#34;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;primary_window&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;primary_window&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;parse_limit_entry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;resolve_limit_window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;percent_left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_percent_left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;reset_time_ms&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;reset_time_ms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reset_time_ms&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;reset_time_ms&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;reset_at&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;window_seconds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;limit_window_seconds&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;percent_left&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;percent_left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;reset_time_ms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reset_time_ms&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;reset_at&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;epoch_ms_to_dt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reset_time_ms&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;limit_window_seconds&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;window_seconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;infer_limit_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;window_seconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;window_seconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;window_seconds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3600&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;window_seconds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;24&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3600&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;relabel_rate_limits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;entry&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;entry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;inferred_name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;infer_limit_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;entry&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;limit_window_seconds&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inferred_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;entry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inferred_name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly&amp;#34;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour&amp;#34;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;parse_rate_limits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;primary_key&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour_limit&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour_rate_limit&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;primary&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;primary_key&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parse_limit_entry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;primary_key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary_key&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly_limit&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly_rate_limit&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;secondary&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary_key&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parse_limit_entry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;secondary_key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parse_limit_entry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;primary_window&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parse_limit_entry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;secondary_window&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;relabel_rate_limits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;primary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secondary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;format_percent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;percent_sort_value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;descending&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;isinstance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;numeric_value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;numeric_value&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;descending&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;numeric_value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_auth_paths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;account_dir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;account_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;base_dir&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;account_dir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;account_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;base_dir&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;account_name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.auth.json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sorted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;base_dir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;glob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;*.auth.json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_account_name_from_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;suffix&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.auth.json&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[:&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;suffix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;endswith&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;suffix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stem&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;build_summary_row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;account_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;five_hour&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;weekly&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;account&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;account_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour_percent&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;five_hour&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;percent_left&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;five_hour&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly_percent&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;weekly&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;percent_left&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;weekly&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly_reset_at&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;weekly&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;reset_at&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;weekly&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;print_summary_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;sorted_rows&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sorted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;percent_sort_value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour_percent&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;descending&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;percent_sort_value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly_percent&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;descending&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;format_cst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly_reset_at&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;account&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;display_rows&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;row&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sorted_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;display_rows&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;s2&#34;&gt;&amp;#34;account&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;account&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format_percent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour_percent&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format_percent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly_percent&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly_reset&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format_cst&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly_reset_at&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;headers&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;account&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;account&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;five_hour%&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly%&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly_reset&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;weekly_reset&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;widths&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]),&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;item&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;display_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;headers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;account&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;widths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;account&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;  &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;five_hour&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;widths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;five_hour&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;  &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;weekly&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;widths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;weekly&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;  &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;weekly_reset&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;widths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;weekly_reset&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;item&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;display_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;account&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;widths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;account&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;  &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;five_hour&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;widths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;five_hour&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;  &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;weekly&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;widths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;weekly&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;  &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;weekly_reset&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;widths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;weekly_reset&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;validate_token_inputs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;account_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;auth_token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;auth_account_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;token&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;startswith&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;sess-&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;status: invalid_token_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;s2&#34;&gt;&amp;#34;message: --chatgpt-token looks like a session token (sess-...). Use the JWT access_token instead.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;s2&#34;&gt;&amp;#34;hint: Found tokens.access_token in auth.json; omit --chatgpt-token or pass that value instead.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;token_exp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;decode_jwt_exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;token_exp&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;token_exp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UTC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;status: expired&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;message: access_token expired at &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;format_dt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;token_exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_token&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_token&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;auth_token_exp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;decode_jwt_exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;auth_token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;hint&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format_dt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;auth_token_exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_token_exp&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;unknown time&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;hint: auth.json contains a different access_token expiring at &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hint&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_account_id&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;account_id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_account_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;warning: supplied --account-id does not match auth.json tokens.account_id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;handle_error_response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;requests&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;raw_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;401&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;status: expired&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;message: Token 已过期或无效&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;raw_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;print_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;403&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;status: forbidden&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;message: 账号已被封禁或无权访问&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;raw_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;print_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;400&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;HTTP &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;print_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fetch_chatgpt_usage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;auth_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;argparse&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Namespace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;auth_data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;load_auth_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;auth_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;account_name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_account_name_from_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;auth_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;auth_token&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_nested_string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;auth_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;tokens&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;access_token&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;auth_account_id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_nested_string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;auth_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;tokens&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;account_id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;account_name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;: auth file not found or invalid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;account_name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;: missing access_token&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_account_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;account_name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;: missing account_id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;validation_error&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;validate_token_inputs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;auth_token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;auth_account_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;auth_token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;auth_account_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;validation_error&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;validation_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;headers&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;Authorization&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Bearer &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;auth_token&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;Accept&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;ChatGPT-Account-Id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_account_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;Origin&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://chatgpt.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;Referer&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://chatgpt.com/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;User-Agent&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Mozilla/5.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;response&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;requests&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;chatgpt_url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timeout&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;requests&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RequestException&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Request failed: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exc&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;raw_headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;=== Headers ===&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;print_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;ValueError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;HTTP &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;error_response&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;handle_error_response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;raw_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;error_response&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;error_response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;raw_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;=== Raw JSON ===&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;print_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;rate_limits&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;first_dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;rate_limit&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;rate_limits&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rate_limits&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;build_summary_row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;account_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;five_hour&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;weekly&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parse_rate_limits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rate_limits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;build_summary_row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;account_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;five_hour&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;weekly&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parse_args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;auth_paths&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_auth_paths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;account_dir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;account_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_paths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;No auth files found.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;exit_code&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;summary_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;JSONDict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_path&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auth_paths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;current_exit_code&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;summary_row&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fetch_chatgpt_usage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;auth_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;exit_code&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exit_code&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;current_exit_code&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;summary_row&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;raw_json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;summary_rows&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;summary_row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;summary_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;print_summary_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;summary_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exit_code&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        </item>
        <item>
        <title>使用AI维护Hugo多语言博客的Agent Skill</title>
        <link>https://knightli.com/2026/04/06/agent-skill-sync-post-translations-guide/</link>
        <pubDate>Mon, 06 Apr 2026 10:00:00 +0800</pubDate>
        
        <guid>https://knightli.com/2026/04/06/agent-skill-sync-post-translations-guide/</guid>
        <description>&lt;p&gt;如果你在维护 Hugo 多语言博客，经常会遇到一个高频痛点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;中文写完后，需要同步生成英文和繁体版本&lt;/li&gt;
&lt;li&gt;三个语言文件要保持结构一致&lt;/li&gt;
&lt;li&gt;front matter 既要翻译又要遵守 Hugo 格式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;sync-post-translations&lt;/code&gt; 就是为这个场景设计的 Agent Skill。&lt;/p&gt;
&lt;h2 id=&#34;这个技能解决什么问题&#34;&gt;这个技能解决什么问题
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;sync-post-translations&lt;/code&gt; 的定位很清晰：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;以 &lt;code&gt;index.zh-cn.md&lt;/code&gt; 为源文件&lt;/li&gt;
&lt;li&gt;在同目录生成或更新 &lt;code&gt;index.en.md&lt;/code&gt;、&lt;code&gt;index.zh-tw.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;保持 Markdown 结构一致&lt;/li&gt;
&lt;li&gt;对 front matter 执行明确规则（尤其是 &lt;code&gt;date&lt;/code&gt;、&lt;code&gt;slug&lt;/code&gt;）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;适用触发词示例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“同步翻译英文繁体”&lt;/li&gt;
&lt;li&gt;“把这篇文章同步成英文和繁体”&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;技能目录结构&#34;&gt;技能目录结构
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.\sync-post-translations\
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├─ SKILL.md
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└─ agents\
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   └─ openai.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;核心代码一skillmd&#34;&gt;核心代码一：SKILL.md
&lt;/h2&gt;&lt;p&gt;下面是该技能的核心规则文件：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;name: sync-post-translations
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;description: 将 Hugo 文章从简体中文源文件（&lt;span class=&#34;sb&#34;&gt;`index.zh-cn.md`&lt;/span&gt;）同步翻译为英文（&lt;span class=&#34;sb&#34;&gt;`index.en.md`&lt;/span&gt;）和繁体中文（&lt;span class=&#34;sb&#34;&gt;`index.zh-tw.md`&lt;/span&gt;）。当用户提出“en 繁体”“同步翻译英文繁体”或要求同时生成/更新两种语言版本且需保持 front matter 与 Markdown 结构一致时使用。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;# 同步文章翻译
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;使用此技能为同一篇文章生成或更新多语言版本。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## 工作流程
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;1.&lt;/span&gt; 在目标文章目录中定位源文件 &lt;span class=&#34;sb&#34;&gt;`index.zh-cn.md`&lt;/span&gt;。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;2.&lt;/span&gt; 读取完整 front matter 与正文内容。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;3.&lt;/span&gt; 在同目录创建或更新 &lt;span class=&#34;sb&#34;&gt;`index.en.md`&lt;/span&gt; 与 &lt;span class=&#34;sb&#34;&gt;`index.zh-tw.md`&lt;/span&gt;。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;4.&lt;/span&gt; 确保三语结构对齐后执行 Hugo 构建检查。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## 翻译规则
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;1.&lt;/span&gt; 严格保留 &lt;span class=&#34;sb&#34;&gt;`slug`&lt;/span&gt; 原值。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;2.&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`date`&lt;/span&gt; 统一规范为 Hugo 常用带时间格式（RFC3339），示例：&lt;span class=&#34;sb&#34;&gt;`2026-04-05T10:00:00+08:00`&lt;/span&gt;。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;3.&lt;/span&gt; 自然翻译以下 front matter 字段：&lt;span class=&#34;sb&#34;&gt;`title`&lt;/span&gt;、&lt;span class=&#34;sb&#34;&gt;`description`&lt;/span&gt;、&lt;span class=&#34;sb&#34;&gt;`tags`&lt;/span&gt;、&lt;span class=&#34;sb&#34;&gt;`categories`&lt;/span&gt;。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;4.&lt;/span&gt; 保持 Markdown 结构不变：标题层级、列表形态、代码块、链接与命令行示例。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;5.&lt;/span&gt; 技术标识符保持原样：文件名、CLI 参数、模型名、设备名、URL、包名等。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;6.&lt;/span&gt; 若 YAML 的 &lt;span class=&#34;sb&#34;&gt;`title`&lt;/span&gt; 含有 &lt;span class=&#34;sb&#34;&gt;`:`&lt;/span&gt;，必须加引号，避免解析报错。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;7.&lt;/span&gt; 在不改变语义前提下，使用目标语言自然标点与表达习惯（&lt;span class=&#34;sb&#34;&gt;`en`&lt;/span&gt;、&lt;span class=&#34;sb&#34;&gt;`zh-tw`&lt;/span&gt;）。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## 输出约定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;1.&lt;/span&gt; 仅在源文章同目录写入目标文件。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;2.&lt;/span&gt; 汇报变更的文件路径。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;3.&lt;/span&gt; 条件允许时执行 &lt;span class=&#34;sb&#34;&gt;`hugo --source . --destination public`&lt;/span&gt;，并反馈通过/失败；失败时给出关键报错行。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## 质量标准
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;1.&lt;/span&gt; 全文术语前后一致。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;2.&lt;/span&gt; 避免机器直译感，优先可发布文风。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;3.&lt;/span&gt; 章节内容完整，不省略示例、注意点与总结。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;核心代码二agentsopenaiyaml&#34;&gt;核心代码二：agents/openai.yaml
&lt;/h2&gt;&lt;p&gt;这个文件定义了技能在 Agent 侧的展示和默认提示词：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;display_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;同步文章翻译&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;short_description&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;生成或更新 EN + ZH-TW 翻译稿&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;default_prompt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;使用该技能在同一 Hugo 文章目录中，从 `index.zh-cn.md` 生成或同步 `index.en.md` 与 `index.zh-tw.md`，保留 `date` 与 `slug`，保持 Markdown 结构一致，并执行 Hugo 构建校验。&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;实战调用示例&#34;&gt;实战调用示例
&lt;/h2&gt;&lt;h3 id=&#34;1-面向人的自然语言触发&#34;&gt;1) 面向人的自然语言触发
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;请把 content/post/2026/04/06/index.zh-cn.md 同步翻译成英文和繁体，
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;要求 date 用 RFC3339，slug 不变，最后跑 hugo 校验。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;2-你应当期待的输出结果&#34;&gt;2) 你应当期待的输出结果
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;已更新：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- content/post/2026/04/06/index.en.md
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- content/post/2026/04/06/index.zh-tw.md
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;构建校验：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- hugo --source . --destination public
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- 结果：PASS
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;为什么这些规则很关键&#34;&gt;为什么这些规则很关键
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;code&gt;slug&lt;/code&gt; 保持不变，能稳定 URL 与历史外链。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;date&lt;/code&gt; 统一 RFC3339（带时区）可避免 Hugo/主题在时间解析上的歧义。&lt;/li&gt;
&lt;li&gt;Markdown 结构不变，能避免翻译后目录、代码块、短代码渲染错位。&lt;/li&gt;
&lt;li&gt;技术标识符不翻译，可显著降低“命令不可用/文件名不匹配”问题。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;常见坑位与规避&#34;&gt;常见坑位与规避
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;code&gt;title&lt;/code&gt; 里有 &lt;code&gt;:&lt;/code&gt; 却没加引号，YAML 会解析失败。&lt;/li&gt;
&lt;li&gt;把 &lt;code&gt;--flag&lt;/code&gt;、URL、包名翻译了，示例命令会直接失效。&lt;/li&gt;
&lt;li&gt;三语标题层级不一致（如中文 &lt;code&gt;##&lt;/code&gt; 变成英文 &lt;code&gt;###&lt;/code&gt;），目录锚点会错位。&lt;/li&gt;
&lt;li&gt;只翻译正文不处理 front matter，页面列表与 SEO 信息会异常。&lt;/li&gt;
&lt;/ol&gt;
</description>
        </item>
        <item>
        <title>如何在 VS Code 中使用 Codex（从安装到高效实战）</title>
        <link>https://knightli.com/2026/03/20/%E5%A6%82%E4%BD%95%E5%9C%A8-vs-code-%E4%B8%AD%E4%BD%BF%E7%94%A8-codex/</link>
        <pubDate>Fri, 20 Mar 2026 00:00:00 +0000</pubDate>
        
        <guid>https://knightli.com/2026/03/20/%E5%A6%82%E4%BD%95%E5%9C%A8-vs-code-%E4%B8%AD%E4%BD%BF%E7%94%A8-codex/</guid>
        <description>&lt;p&gt;Codex 可以直接在 VS Code 侧边栏中协助你写代码、改 Bug、解释项目和执行命令。&lt;/p&gt;
&lt;h2 id=&#34;1-准备工作&#34;&gt;1. 准备工作
&lt;/h2&gt;&lt;p&gt;开始前请确认：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;VS Code 已更新到较新的稳定版本。&lt;/li&gt;
&lt;li&gt;你可以正常访问OpenAi网站&lt;/li&gt;
&lt;li&gt;项目代码已在本地打开（建议使用 Git 仓库）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;2-安装扩展&#34;&gt;2. 安装扩展
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;打开 VS Code 的扩展市场（Extensions）。&lt;/li&gt;
&lt;li&gt;搜索并安装：&lt;code&gt;Codex - Codex - OpenAI&#39;s coding agent&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;安装完成后，按提示完成登录授权。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;3-打开-codex-侧边栏&#34;&gt;3. 打开 Codex 侧边栏
&lt;/h2&gt;&lt;p&gt;你可以通过任一方式打开：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在编辑器右上角点击 &lt;code&gt;Open Codex Sidebar&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;使用命令面板（&lt;code&gt;Ctrl + Shift + P&lt;/code&gt;）搜索 &lt;code&gt;Codex&lt;/code&gt; 并打开。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;打开后，Codex 会读取当前工作区上下文，进入可对话状态。&lt;/p&gt;
&lt;h2 id=&#34;4-常见使用方式&#34;&gt;4. 常见使用方式
&lt;/h2&gt;&lt;h3 id=&#34;41-让它解释代码&#34;&gt;4.1 让它解释代码
&lt;/h3&gt;&lt;p&gt;示例提示词：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;请解释这个文件的核心逻辑，并指出最可能出错的 3 个地方。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;适合你刚接手旧项目时快速建立全局理解。&lt;/p&gt;
&lt;h3 id=&#34;42-让它实现功能&#34;&gt;4.2 让它实现功能
&lt;/h3&gt;&lt;p&gt;示例提示词：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;在现有 API 里新增一个 /healthz 健康检查接口，
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;要求返回版本号和数据库连接状态，并补上基础测试。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;建议把“输入约束”和“验收标准”一起写清楚，生成结果会稳定很多。&lt;/p&gt;
&lt;h3 id=&#34;43-让它修复问题&#34;&gt;4.3 让它修复问题
&lt;/h3&gt;&lt;p&gt;示例提示词：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;这个接口在并发下偶发 500，请先定位根因，再给出最小改动修复方案，
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;最后列出回归测试点。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;先“定位”再“修复”，能减少误改和过度重构。&lt;/p&gt;
&lt;h2 id=&#34;5-高质量提示词模板&#34;&gt;5. 高质量提示词模板
&lt;/h2&gt;&lt;p&gt;你可以直接复用下面这个结构：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;背景：这是一个 &amp;lt;技术栈&amp;gt; 项目，当前目标是 &amp;lt;目标&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;约束：不改动 &amp;lt;模块/接口&amp;gt;，兼容 &amp;lt;版本/平台&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;输出：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1) 修改文件列表
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2) 关键代码说明
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;3) 验证步骤
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;4) 风险与回滚方案
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个模板对“多人协作 + 大项目”非常有帮助。&lt;/p&gt;
&lt;h2 id=&#34;6-常见问题&#34;&gt;6. 常见问题
&lt;/h2&gt;&lt;h3 id=&#34;61-关于免费额度&#34;&gt;6.1 关于免费额度
&lt;/h3&gt;&lt;p&gt;在对话框输入 &amp;lsquo;&#39; 然后选择 状态会出现 额度 重置时间等相关信息&lt;/p&gt;
&lt;h3 id=&#34;62-改动不符合预期&#34;&gt;6.2 改动不符合预期
&lt;/h3&gt;&lt;p&gt;修改完成后查看审核按钮，查看修改细节，不满意选择撤销按钮，可撤销修改。
在后面的步骤中可以把需求拆小，分成多个步骤分别执行。
使用git等代码管理工具，保持小步提交（small commits），方便回滚。&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
