在 Claude Code 中以 MCP 接入 Codex

<p>Codex CLI 的命令行交互较为原始,沙箱环境存在不少 bug,执行命令时也受到诸多限制。相比之下,Claude Code 的设计更加完善,支持 MCP、Plugin、Skill、Agent 等多种自定义扩展形式。将 Codex 作为 MCP 服务器接入 Claude Code,可以获得更友好的用户体验和更强大的功能集成。</p> <!--more--> <h2 id="为什么选择-mcp-方式而非直接使用-codex-cli">为什么选择 MCP 方式而非直接使用 Codex CLI</h2> <h3 id="codex-cli-的局限性">Codex CLI 的局限性</h3> <ul> <li><strong>命令行交互原始</strong>:缺乏现代化的交互体验,错误提示不够清晰</li> <li><strong>沙箱环境 bug 多</strong>:执行复杂任务时容易遇到环境问题</li> <li><strong>命令执行受限</strong>:某些操作在沙箱中无法正常执行,自由度较低</li> </ul> <h3 id="claude-code-的优势">Claude Code 的优势</h3> <ul> <li><strong>设计完善</strong>:提供更流畅的代码编辑和 AI 交互体验</li> <li><strong>扩展性强</strong>:支持 MCP、Plugin、Skill、Agent 等多种扩展方式</li> <li><strong>工具集成</strong>:可以无缝整合多种工具和服务</li> <li><strong>用户体验友好</strong>:界面直观,错误处理更完善</li> </ul> <p>通过 MCP 方式,Codex 可以作为 Claude Code 的一个工具被调用,既保留了 Codex 的能力,又享受了 Claude Code 的完善生态。</p> <hr /> <h2 id="前置要求">前置要求</h2> <ul> <li>已安装 Claude Code CLI(可通过 <code class="language-plaintext highlighter-rouge">claude -v</code> 验证)</li> <li>已安装 Codex CLI,并能在终端调用 <code class="language-plaintext highlighter-rouge">codex</code> 命令</li> </ul> <hr /> <h2 id="配置步骤">配置步骤</h2> <h3 id="一条命令完成添加用户作用域">一条命令完成添加(用户作用域)</h3> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>claude mcp add codex <span class="nt">-s</span> user <span class="nt">--</span> codex <span class="nt">-m</span> gpt-5.3-codex <span class="nt">-c</span> <span class="nv">model_reasoning_effort</span><span class="o">=</span><span class="s2">"high"</span> mcp-server </code></pre></div></div> <p><strong>参数说明:</strong></p> <ul> <li><code class="language-plaintext highlighter-rouge">-s user</code>:将服务器写入用户全局配置,所有项目可用且不会改动仓库文件</li> <li><code class="language-plaintext highlighter-rouge">--</code>:分隔 Claude MCP 参数与实际服务器启动命令</li> <li><code class="language-plaintext highlighter-rouge">codex -m gpt-5.3-codex-max</code>:指定要暴露的 Codex 模型</li> <li><code class="language-plaintext highlighter-rouge">-c model_reasoning_effort="high"</code>:为 Codex 进程设置高推理强度</li> <li><code class="language-plaintext highlighter-rouge">mcp-server</code>:启动 Codex 的 MCP 服务器模式</li> </ul> <h3 id="验证配置是否生效">验证配置是否生效</h3> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 列出所有 MCP 服务器</span> claude mcp list <span class="c"># 查看 codex 服务器详情</span> claude mcp get codex </code></pre></div></div> <p>若能看到 <code class="language-plaintext highlighter-rouge">type: stdio</code> 且状态为 running/available,说明已成功接入。</p> <hr /> <h2 id="在-claude-code-中使用">在 Claude Code 中使用</h2> <ol> <li>打开 Claude Code,在对话中输入 <code class="language-plaintext highlighter-rouge">/mcp</code> 命令</li> <li>选择 <code class="language-plaintext highlighter-rouge">codex</code> 服务器</li> <li>直接在对话中调用 Codex 暴露的工具;如需指定模型,可在提示中写明 <code class="language-plaintext highlighter-rouge">gpt-5.3-codex</code></li> </ol> <p>现在你可以在 Claude Code 的完善环境中使用 Codex 的能力,同时享受更好的交互体验和工具集成。</p> <hr /> <h2 id="常见问题">常见问题</h2> <ul> <li><strong>找不到 <code class="language-plaintext highlighter-rouge">claude</code> 命令</strong>:确保已安装 Claude Code CLI 并已加入系统 PATH</li> <li><strong>找不到 <code class="language-plaintext highlighter-rouge">codex</code> 命令</strong>:先安装 Codex CLI(参考 Codex 官方安装说明),或检查 shell PATH 配置</li> <li><strong>想移除服务器</strong>:使用 <code class="language-plaintext highlighter-rouge">claude mcp remove codex</code> 命令</li> <li><strong>切换配置作用域</strong>:如需改用项目级配置,先删除用户级配置,再按需添加项目级配置</li> </ul>

2025/12/13
阅读更多

Claude Code 插件与 Hook 开发完整教程

<p>Claude Code 提供了强大的插件系统,允许你通过自定义命令、代理、Hook、Skills 和 MCP 服务器来扩展功能。本文将完整介绍如何从零开始开发 Claude Code 插件和 Hook,包括创建插件、配置 Hook、发布到 Marketplace 等全流程。</p> <!--more--> <h2 id="为什么需要插件系统">为什么需要插件系统</h2> <p>Claude Code 的插件系统提供了多种扩展方式:</p> <ul> <li><strong>Commands(命令)</strong>:创建自定义斜杠命令,快速执行常用操作</li> <li><strong>Agents(代理)</strong>:定义专门的子代理来处理特定任务</li> <li><strong>Skills(技能)</strong>:扩展 Claude 的能力,让模型自主调用</li> <li><strong>Hooks(钩子)</strong>:在特定事件发生时自动执行脚本</li> <li><strong>MCP Servers</strong>:集成外部工具和服务</li> </ul> <p>通过插件系统,你可以:</p> <ul> <li><strong>自动化工作流</strong>:在文件写入后自动格式化、运行测试</li> <li><strong>增强安全性</strong>:拦截危险操作、验证命令</li> <li><strong>集成工具</strong>:连接数据库、API、通知系统等</li> <li><strong>团队协作</strong>:在项目级别配置插件,确保团队使用一致的工具</li> </ul> <hr /> <h2 id="快速开始创建第一个插件">快速开始:创建第一个插件</h2> <p>让我们通过创建一个简单的问候插件来熟悉插件系统。</p> <h3 id="前置要求">前置要求</h3> <ul> <li>已安装 Claude Code(可通过 <code class="language-plaintext highlighter-rouge">claude -v</code> 验证)</li> <li>基本的命令行操作知识</li> </ul> <h3 id="步骤-1创建-marketplace-结构">步骤 1:创建 Marketplace 结构</h3> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir </span>test-marketplace <span class="nb">cd </span>test-marketplace </code></pre></div></div> <h3 id="步骤-2创建插件目录">步骤 2:创建插件目录</h3> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir </span>my-first-plugin <span class="nb">cd </span>my-first-plugin </code></pre></div></div> <h3 id="步骤-3创建插件清单文件">步骤 3:创建插件清单文件</h3> <p>插件清单文件 <code class="language-plaintext highlighter-rouge">.claude-plugin/plugin.json</code> 描述了插件的基本信息:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> .claude-plugin <span class="nb">cat</span> <span class="o">&gt;</span> .claude-plugin/plugin.json <span class="o">&lt;&lt;</span> <span class="sh">'</span><span class="no">EOF</span><span class="sh">' { "name": "my-first-plugin", "description": "一个简单的问候插件,用于学习基础知识", "version": "1.0.0", "author": { "name": "Your Name" } } </span><span class="no">EOF </span></code></pre></div></div> <h3 id="步骤-4添加自定义命令">步骤 4:添加自定义命令</h3> <p>在 <code class="language-plaintext highlighter-rouge">commands/</code> 目录下创建命令文件:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir </span>commands <span class="nb">cat</span> <span class="o">&gt;</span> commands/hello.md <span class="o">&lt;&lt;</span> <span class="sh">'</span><span class="no">EOF</span><span class="sh">' --- description: 用个性化的消息问候用户 --- # Hello Command 热情地问候用户,并询问今天能如何帮助他们。让问候更加个性化和鼓励性。 </span><span class="no">EOF </span></code></pre></div></div> <h3 id="步骤-5创建-marketplace-清单">步骤 5:创建 Marketplace 清单</h3> <p>返回上级目录,创建 Marketplace 配置文件:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> .. <span class="nb">mkdir</span> .claude-plugin <span class="nb">cat</span> <span class="o">&gt;</span> .claude-plugin/marketplace.json <span class="o">&lt;&lt;</span> <span class="sh">'</span><span class="no">EOF</span><span class="sh">' { "name": "test-marketplace", "owner": { "name": "Test User" }, "plugins": [ { "name": "my-first-plugin", "source": "./my-first-plugin", "description": "我的第一个测试插件" } ] } </span><span class="no">EOF </span></code></pre></div></div> <h3 id="步骤-6安装和测试">步骤 6:安装和测试</h3> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 从父目录启动 Claude Code</span> <span class="nb">cd</span> .. claude <span class="c"># 在 Claude Code 中添加测试 Marketplace</span> /plugin marketplace add ./test-marketplace <span class="c"># 安装你的插件</span> /plugin <span class="nb">install </span>my-first-plugin@test-marketplace </code></pre></div></div> <p>选择 “Install now”,然后需要重启 Claude Code 才能使用新插件。</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 尝试你的新命令</span> /hello </code></pre></div></div> <p>你会看到 Claude 使用你的问候命令!运行 <code class="language-plaintext highlighter-rouge">/help</code> 可以查看新命令是否已列出。</p> <hr /> <h2 id="插件结构详解">插件结构详解</h2> <p>一个完整的插件可以包含以下组件:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>my-plugin/ ├── .claude-plugin/ │ └── plugin.json # 插件元数据(必需) ├── commands/ # 自定义斜杠命令(可选) │ └── hello.md ├── agents/ # 自定义代理(可选) │ └── helper.md ├── skills/ # Agent Skills(可选) │ └── my-skill/ │ └── SKILL.md ├── hooks/ # 事件处理器(可选) │ └── hooks.json └── .mcp.json # MCP 服务器配置(可选) </code></pre></div></div> <h3 id="插件清单pluginjson">插件清单(plugin.json)</h3> <p>这是插件的核心配置文件,必须包含:</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"plugin-name"</span><span class="p">,</span><span class="w"> </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"插件描述"</span><span class="p">,</span><span class="w"> </span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nl">"author"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"作者名称"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <h3 id="commands命令">Commands(命令)</h3> <p>Commands 是自定义的斜杠命令,通过 Markdown 文件定义。文件内容会被发送给 Claude 作为指令。</p> <p><strong>示例:代码格式化命令</strong></p> <div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span> <span class="na">description</span><span class="pi">:</span> <span class="s">自动格式化当前项目的代码</span> <span class="nn">---</span> <span class="gh"># Format Command</span> 格式化当前项目中的所有代码文件。使用项目配置的格式化工具(如 Prettier、Black 等)。 确保遵循项目的代码风格指南。 </code></pre></div></div> <h3 id="agents代理">Agents(代理)</h3> <p>Agents 是专门的子代理,用于处理特定类型的任务。</p> <p><strong>示例:代码审查代理</strong></p> <div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span> <span class="na">description</span><span class="pi">:</span> <span class="s">专业的代码审查助手</span> <span class="nn">---</span> <span class="gh"># Code Review Agent</span> 你是一个专业的代码审查助手。你的任务是: <span class="p">1.</span> 仔细审查代码的质量、可读性和最佳实践 <span class="p">2.</span> 识别潜在的安全漏洞和性能问题 <span class="p">3.</span> 提供建设性的反馈和改进建议 <span class="p">4.</span> 确保代码符合项目的编码标准 </code></pre></div></div> <h3 id="skills技能">Skills(技能)</h3> <p>Skills 是模型可以自主调用的能力扩展。创建 <code class="language-plaintext highlighter-rouge">skills/</code> 目录,每个技能是一个包含 <code class="language-plaintext highlighter-rouge">SKILL.md</code> 的子目录。</p> <p><strong>示例:Git 操作技能</strong></p> <div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gh"># Git Operations Skill</span> 这个技能允许 Claude 执行常见的 Git 操作,如提交、推送、创建分支等。 Claude 可以在需要版本控制操作时自动使用此技能。 </code></pre></div></div> <hr /> <h2 id="hook-开发详解">Hook 开发详解</h2> <p>Hook 是插件系统中最强大的功能之一,允许你在特定事件发生时自动执行脚本。</p> <h3 id="hook-配置位置">Hook 配置位置</h3> <p>Hook 可以在以下位置配置:</p> <ul> <li><code class="language-plaintext highlighter-rouge">~/.claude/settings.json</code> - 用户级设置</li> <li><code class="language-plaintext highlighter-rouge">.claude/settings.json</code> - 项目级设置</li> <li><code class="language-plaintext highlighter-rouge">.claude/settings.local.json</code> - 本地项目设置(不提交)</li> <li>插件中的 <code class="language-plaintext highlighter-rouge">hooks/hooks.json</code> - 插件提供的 Hook</li> </ul> <h3 id="hook-事件类型">Hook 事件类型</h3> <h4 id="pretooluse">PreToolUse</h4> <p>在工具调用之前执行,可以拦截、修改或自动批准操作。</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"PreToolUse"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"matcher"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Write|Edit"</span><span class="p">,</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"command"</span><span class="p">,</span><span class="w"> </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="s2">"$CLAUDE_PROJECT_DIR/.claude/hooks/validate-write.sh"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <h4 id="posttooluse">PostToolUse</h4> <p>在工具成功执行后立即运行,常用于自动格式化、运行测试等。</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"PostToolUse"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"matcher"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Write|Edit"</span><span class="p">,</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"command"</span><span class="p">,</span><span class="w"> </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="s2">"$CLAUDE_PROJECT_DIR/.claude/hooks/format-code.sh"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <h4 id="notification">Notification</h4> <p>当 Claude Code 发送通知时触发,可以用于桌面通知、日志记录等。</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"Notification"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"matcher"</span><span class="p">:</span><span class="w"> </span><span class="s2">"permission_prompt"</span><span class="p">,</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"command"</span><span class="p">,</span><span class="w"> </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/path/to/notification.sh"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <h4 id="userpromptsubmit">UserPromptSubmit</h4> <p>在用户提交提示之前执行,可以添加上下文、验证提示等。</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"UserPromptSubmit"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"command"</span><span class="p">,</span><span class="w"> </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="s2">"$CLAUDE_PROJECT_DIR/.claude/hooks/add-context.sh"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <h4 id="sessionstart--sessionend">SessionStart / SessionEnd</h4> <p>在会话开始或结束时执行,用于环境设置、清理任务等。</p> <h3 id="hook-输入和输出">Hook 输入和输出</h3> <p>Hook 通过 stdin 接收 JSON 数据,包含会话信息和事件特定数据:</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"session_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"abc123"</span><span class="p">,</span><span class="w"> </span><span class="nl">"transcript_path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/path/to/transcript.jsonl"</span><span class="p">,</span><span class="w"> </span><span class="nl">"cwd"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/current/working/directory"</span><span class="p">,</span><span class="w"> </span><span class="nl">"permission_mode"</span><span class="p">:</span><span class="w"> </span><span class="s2">"default"</span><span class="p">,</span><span class="w"> </span><span class="nl">"hook_event_name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"PostToolUse"</span><span class="p">,</span><span class="w"> </span><span class="nl">"tool_name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Write"</span><span class="p">,</span><span class="w"> </span><span class="nl">"tool_input"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"file_path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/path/to/file.txt"</span><span class="p">,</span><span class="w"> </span><span class="nl">"content"</span><span class="p">:</span><span class="w"> </span><span class="s2">"file content"</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nl">"tool_response"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"filePath"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/path/to/file.txt"</span><span class="p">,</span><span class="w"> </span><span class="nl">"success"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <h3 id="hook-输出控制">Hook 输出控制</h3> <p>Hook 可以通过退出码和 JSON 输出来控制行为:</p> <p><strong>简单方式:退出码</strong></p> <ul> <li><code class="language-plaintext highlighter-rouge">0</code>:成功,stdout 在详细模式下显示</li> <li><code class="language-plaintext highlighter-rouge">2</code>:阻止操作,stderr 作为错误消息返回给 Claude</li> <li>其他:非阻塞错误,stderr 在详细模式下显示</li> </ul> <p><strong>高级方式:JSON 输出</strong></p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"decision"</span><span class="p">:</span><span class="w"> </span><span class="s2">"block"</span><span class="p">,</span><span class="w"> </span><span class="nl">"reason"</span><span class="p">:</span><span class="w"> </span><span class="s2">"解释为什么阻止操作"</span><span class="p">,</span><span class="w"> </span><span class="nl">"hookSpecificOutput"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"hookEventName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"PreToolUse"</span><span class="p">,</span><span class="w"> </span><span class="nl">"permissionDecision"</span><span class="p">:</span><span class="w"> </span><span class="s2">"deny"</span><span class="p">,</span><span class="w"> </span><span class="nl">"permissionDecisionReason"</span><span class="p">:</span><span class="w"> </span><span class="s2">"此操作被安全策略阻止"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <hr /> <h2 id="实战案例通知插件开发">实战案例:通知插件开发</h2> <p>让我们参考 <a href="https://github.com/discountry/ritmex-marketplace">ritmex-marketplace</a> 来创建一个完整的通知插件。</p> <h3 id="项目结构">项目结构</h3> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ritmex-marketplace/ ├── .claude-plugin/ │ └── marketplace.json # Marketplace 配置 ├── claude-code-notification/ # 通知插件 │ ├── .claude-plugin/ │ │ └── plugin.json # 插件清单 │ ├── hooks/ │ │ └── hooks.json # Hook 配置 │ └── scripts/ │ └── notification.sh # 通知脚本 └── README.md </code></pre></div></div> <h3 id="marketplace-配置">Marketplace 配置</h3> <p><code class="language-plaintext highlighter-rouge">.claude-plugin/marketplace.json</code>:</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ritmex-marketplace"</span><span class="p">,</span><span class="w"> </span><span class="nl">"owner"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"discountry"</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nl">"plugins"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"claude-code-notification"</span><span class="p">,</span><span class="w"> </span><span class="nl">"source"</span><span class="p">:</span><span class="w"> </span><span class="s2">"./claude-code-notification"</span><span class="p">,</span><span class="w"> </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"在 macOS 上显示 Claude Code 通知"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <h3 id="插件清单">插件清单</h3> <p><code class="language-plaintext highlighter-rouge">claude-code-notification/.claude-plugin/plugin.json</code>:</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"claude-code-notification"</span><span class="p">,</span><span class="w"> </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"当 Claude Code 触发 Notification hook 时显示 macOS 通知"</span><span class="p">,</span><span class="w"> </span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nl">"author"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"discountry"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <h3 id="hook-配置">Hook 配置</h3> <p><code class="language-plaintext highlighter-rouge">claude-code-notification/hooks/hooks.json</code>:</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"自动显示 macOS 通知"</span><span class="p">,</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"Notification"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"matcher"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"command"</span><span class="p">,</span><span class="w"> </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="s2">"${CLAUDE_PLUGIN_ROOT}/scripts/notification.sh"</span><span class="p">,</span><span class="w"> </span><span class="nl">"timeout"</span><span class="p">:</span><span class="w"> </span><span class="mi">30</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <h3 id="通知脚本">通知脚本</h3> <p><code class="language-plaintext highlighter-rouge">claude-code-notification/scripts/notification.sh</code>:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span> <span class="c"># 读取 JSON 输入</span> <span class="nv">INPUT</span><span class="o">=</span><span class="si">$(</span><span class="nb">cat</span><span class="si">)</span> <span class="nv">MESSAGE</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$INPUT</span><span class="s2">"</span> | jq <span class="nt">-r</span> <span class="s1">'.message // "Claude Code Notification"'</span><span class="si">)</span> <span class="nv">NOTIFICATION_TYPE</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$INPUT</span><span class="s2">"</span> | jq <span class="nt">-r</span> <span class="s1">'.notification_type // ""'</span><span class="si">)</span> <span class="nv">TRANSCRIPT_PATH</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$INPUT</span><span class="s2">"</span> | jq <span class="nt">-r</span> <span class="s1">'.transcript_path // ""'</span><span class="si">)</span> <span class="c"># 设置通知标题</span> <span class="nv">TITLE</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">CLAUDE_NOTIFY_TITLE</span><span class="k">:-</span><span class="nv">Claude</span><span class="p"> Code</span><span class="k">}</span><span class="s2">"</span> <span class="c"># 根据通知类型设置点击行为</span> <span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$NOTIFICATION_TYPE</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"permission_prompt"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> <span class="c"># 权限提示:点击时聚焦到终端</span> <span class="k">if </span><span class="nb">command</span> <span class="nt">-v</span> terminal-notifier &amp;&gt; /dev/null<span class="p">;</span> <span class="k">then </span>terminal-notifier <span class="se">\</span> <span class="nt">-title</span> <span class="s2">"</span><span class="nv">$TITLE</span><span class="s2">"</span> <span class="se">\</span> <span class="nt">-message</span> <span class="s2">"</span><span class="nv">$MESSAGE</span><span class="s2">"</span> <span class="se">\</span> <span class="nt">-activate</span> <span class="s2">"com.warp.Warp"</span> <span class="se">\</span> <span class="nt">-sender</span> <span class="s2">"com.warp.Warp"</span> 2&gt;/dev/null <span class="o">||</span> <span class="se">\</span> terminal-notifier <span class="se">\</span> <span class="nt">-title</span> <span class="s2">"</span><span class="nv">$TITLE</span><span class="s2">"</span> <span class="se">\</span> <span class="nt">-message</span> <span class="s2">"</span><span class="nv">$MESSAGE</span><span class="s2">"</span> <span class="se">\</span> <span class="nt">-activate</span> <span class="s2">"com.apple.Terminal"</span> <span class="se">\</span> <span class="nt">-sender</span> <span class="s2">"com.apple.Terminal"</span> <span class="k">else</span> <span class="c"># 使用 osascript 作为后备</span> osascript <span class="nt">-e</span> <span class="s2">"display notification </span><span class="se">\"</span><span class="nv">$MESSAGE</span><span class="se">\"</span><span class="s2"> with title </span><span class="se">\"</span><span class="nv">$TITLE</span><span class="se">\"</span><span class="s2">"</span> <span class="k">fi elif</span> <span class="o">[</span> <span class="nt">-n</span> <span class="s2">"</span><span class="nv">$TRANSCRIPT_PATH</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span> <span class="c"># 有 transcript 路径:点击时打开文件</span> <span class="k">if </span><span class="nb">command</span> <span class="nt">-v</span> terminal-notifier &amp;&gt; /dev/null<span class="p">;</span> <span class="k">then </span>terminal-notifier <span class="se">\</span> <span class="nt">-title</span> <span class="s2">"</span><span class="nv">$TITLE</span><span class="s2">"</span> <span class="se">\</span> <span class="nt">-message</span> <span class="s2">"</span><span class="nv">$MESSAGE</span><span class="s2">"</span> <span class="se">\</span> <span class="nt">-open</span> <span class="s2">"</span><span class="nv">$TRANSCRIPT_PATH</span><span class="s2">"</span> <span class="k">else </span>osascript <span class="nt">-e</span> <span class="s2">"display notification </span><span class="se">\"</span><span class="nv">$MESSAGE</span><span class="se">\"</span><span class="s2"> with title </span><span class="se">\"</span><span class="nv">$TITLE</span><span class="se">\"</span><span class="s2">"</span> <span class="k">fi else</span> <span class="c"># 普通通知</span> <span class="k">if </span><span class="nb">command</span> <span class="nt">-v</span> terminal-notifier &amp;&gt; /dev/null<span class="p">;</span> <span class="k">then </span>terminal-notifier <span class="nt">-title</span> <span class="s2">"</span><span class="nv">$TITLE</span><span class="s2">"</span> <span class="nt">-message</span> <span class="s2">"</span><span class="nv">$MESSAGE</span><span class="s2">"</span> <span class="k">else </span>osascript <span class="nt">-e</span> <span class="s2">"display notification </span><span class="se">\"</span><span class="nv">$MESSAGE</span><span class="se">\"</span><span class="s2"> with title </span><span class="se">\"</span><span class="nv">$TITLE</span><span class="se">\"</span><span class="s2">"</span> <span class="k">fi fi </span><span class="nb">exit </span>0 </code></pre></div></div> <h3 id="安装和使用">安装和使用</h3> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 添加 Marketplace</span> /plugin marketplace add discountry/ritmex-marketplace <span class="c"># 安装插件</span> /plugin <span class="nb">install </span>claude-code-notification@ritmex-marketplace <span class="c"># 验证安装</span> /plugin </code></pre></div></div> <hr /> <h2 id="高级-hook-示例">高级 Hook 示例</h2> <h3 id="示例-1自动代码格式化">示例 1:自动代码格式化</h3> <p>在文件写入后自动运行格式化工具:</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"PostToolUse"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"matcher"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Write|Edit"</span><span class="p">,</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"command"</span><span class="p">,</span><span class="w"> </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="s2">"$CLAUDE_PROJECT_DIR/.claude/hooks/format.sh"</span><span class="p">,</span><span class="w"> </span><span class="nl">"timeout"</span><span class="p">:</span><span class="w"> </span><span class="mi">30</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <p><code class="language-plaintext highlighter-rouge">format.sh</code>:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span> <span class="nv">INPUT</span><span class="o">=</span><span class="si">$(</span><span class="nb">cat</span><span class="si">)</span> <span class="nv">FILE_PATH</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$INPUT</span><span class="s2">"</span> | jq <span class="nt">-r</span> <span class="s1">'.tool_response.filePath // .tool_input.file_path // ""'</span><span class="si">)</span> <span class="k">if</span> <span class="o">[</span> <span class="nt">-z</span> <span class="s2">"</span><span class="nv">$FILE_PATH</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then </span><span class="nb">exit </span>0 <span class="k">fi</span> <span class="c"># 根据文件类型选择格式化工具</span> <span class="k">case</span> <span class="s2">"</span><span class="nv">$FILE_PATH</span><span class="s2">"</span> <span class="k">in</span> <span class="k">*</span>.js|<span class="k">*</span>.jsx|<span class="k">*</span>.ts|<span class="k">*</span>.tsx|<span class="k">*</span>.json<span class="p">)</span> <span class="k">if </span><span class="nb">command</span> <span class="nt">-v</span> prettier &amp;&gt; /dev/null<span class="p">;</span> <span class="k">then </span>prettier <span class="nt">--write</span> <span class="s2">"</span><span class="nv">$FILE_PATH</span><span class="s2">"</span> 2&gt;/dev/null <span class="k">fi</span> <span class="p">;;</span> <span class="k">*</span>.py<span class="p">)</span> <span class="k">if </span><span class="nb">command</span> <span class="nt">-v</span> black &amp;&gt; /dev/null<span class="p">;</span> <span class="k">then </span>black <span class="s2">"</span><span class="nv">$FILE_PATH</span><span class="s2">"</span> 2&gt;/dev/null <span class="k">fi</span> <span class="p">;;</span> <span class="k">*</span>.go<span class="p">)</span> <span class="k">if </span><span class="nb">command</span> <span class="nt">-v</span> gofmt &amp;&gt; /dev/null<span class="p">;</span> <span class="k">then </span>gofmt <span class="nt">-w</span> <span class="s2">"</span><span class="nv">$FILE_PATH</span><span class="s2">"</span> 2&gt;/dev/null <span class="k">fi</span> <span class="p">;;</span> <span class="k">esac</span> <span class="nb">exit </span>0 </code></pre></div></div> <h3 id="示例-2命令验证">示例 2:命令验证</h3> <p>拦截危险命令并建议更安全的替代方案:</p> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3 </span><span class="kn">import</span> <span class="nn">json</span> <span class="kn">import</span> <span class="nn">re</span> <span class="kn">import</span> <span class="nn">sys</span> <span class="n">VALIDATION_RULES</span> <span class="o">=</span> <span class="p">[</span> <span class="p">(</span> <span class="sa">r</span><span class="s">"\bgrep\b(?!.*\|)"</span><span class="p">,</span> <span class="s">"建议使用 'rg' (ripgrep) 替代 'grep',性能更好且功能更强大"</span><span class="p">,</span> <span class="p">),</span> <span class="p">(</span> <span class="sa">r</span><span class="s">"\bfind\s+\S+\s+-name\b"</span><span class="p">,</span> <span class="s">"建议使用 'rg --files | rg pattern' 替代 'find -name',性能更好"</span><span class="p">,</span> <span class="p">),</span> <span class="p">(</span> <span class="sa">r</span><span class="s">"rm\s+-rf\s+/"</span><span class="p">,</span> <span class="s">"危险操作:删除根目录!请确认这是你想要的。"</span><span class="p">,</span> <span class="p">),</span> <span class="p">]</span> <span class="k">try</span><span class="p">:</span> <span class="n">input_data</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">stdin</span><span class="p">)</span> <span class="k">except</span> <span class="n">json</span><span class="p">.</span><span class="n">JSONDecodeError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"错误: 无效的 JSON 输入: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s">"</span><span class="p">,</span> <span class="nb">file</span><span class="o">=</span><span class="n">sys</span><span class="p">.</span><span class="n">stderr</span><span class="p">)</span> <span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="n">tool_name</span> <span class="o">=</span> <span class="n">input_data</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">"tool_name"</span><span class="p">,</span> <span class="s">""</span><span class="p">)</span> <span class="n">tool_input</span> <span class="o">=</span> <span class="n">input_data</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">"tool_input"</span><span class="p">,</span> <span class="p">{})</span> <span class="n">command</span> <span class="o">=</span> <span class="n">tool_input</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">"command"</span><span class="p">,</span> <span class="s">""</span><span class="p">)</span> <span class="k">if</span> <span class="n">tool_name</span> <span class="o">!=</span> <span class="s">"Bash"</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">command</span><span class="p">:</span> <span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="n">issues</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">pattern</span><span class="p">,</span> <span class="n">message</span> <span class="ow">in</span> <span class="n">VALIDATION_RULES</span><span class="p">:</span> <span class="k">if</span> <span class="n">re</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="n">pattern</span><span class="p">,</span> <span class="n">command</span><span class="p">):</span> <span class="n">issues</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">message</span><span class="p">)</span> <span class="k">if</span> <span class="n">issues</span><span class="p">:</span> <span class="k">for</span> <span class="n">message</span> <span class="ow">in</span> <span class="n">issues</span><span class="p">:</span> <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"• </span><span class="si">{</span><span class="n">message</span><span class="si">}</span><span class="s">"</span><span class="p">,</span> <span class="nb">file</span><span class="o">=</span><span class="n">sys</span><span class="p">.</span><span class="n">stderr</span><span class="p">)</span> <span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="c1"># 阻止命令执行 </span> <span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> </code></pre></div></div> <h3 id="示例-3智能停止判断">示例 3:智能停止判断</h3> <p>使用 LLM 判断 Claude 是否应该继续工作:</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"Stop"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"prompt"</span><span class="p">,</span><span class="w"> </span><span class="nl">"prompt"</span><span class="p">:</span><span class="w"> </span><span class="s2">"评估 Claude 是否应该停止工作。上下文: $ARGUMENTS</span><span class="se">\n\n</span><span class="s2">分析对话并判断:</span><span class="se">\n</span><span class="s2">1. 用户请求的所有任务是否已完成</span><span class="se">\n</span><span class="s2">2. 是否有需要解决的错误</span><span class="se">\n</span><span class="s2">3. 是否需要后续工作</span><span class="se">\n\n</span><span class="s2">返回 JSON: {</span><span class="se">\"</span><span class="s2">decision</span><span class="se">\"</span><span class="s2">: </span><span class="se">\"</span><span class="s2">approve</span><span class="se">\"</span><span class="s2"> 或 </span><span class="se">\"</span><span class="s2">block</span><span class="se">\"</span><span class="s2">, </span><span class="se">\"</span><span class="s2">reason</span><span class="se">\"</span><span class="s2">: </span><span class="se">\"</span><span class="s2">你的解释</span><span class="se">\"</span><span class="s2">}"</span><span class="p">,</span><span class="w"> </span><span class="nl">"timeout"</span><span class="p">:</span><span class="w"> </span><span class="mi">30</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <hr /> <h2 id="发布和分发插件">发布和分发插件</h2> <h3 id="创建-github-marketplace">创建 GitHub Marketplace</h3> <ol> <li><strong>创建仓库结构</strong>:</li> </ol> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir </span>my-marketplace <span class="nb">cd </span>my-marketplace <span class="nb">mkdir</span> .claude-plugin <span class="c"># 创建 marketplace.json</span> <span class="c"># 添加插件目录</span> </code></pre></div></div> <ol> <li><strong>推送到 GitHub</strong>:</li> </ol> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git init git add <span class="nb">.</span> git commit <span class="nt">-m</span> <span class="s2">"Initial marketplace"</span> git remote add origin https://github.com/your-org/my-marketplace.git git push <span class="nt">-u</span> origin main </code></pre></div></div> <ol> <li><strong>用户安装</strong>:</li> </ol> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/plugin marketplace add your-org/my-marketplace /plugin <span class="nb">install </span>plugin-name@my-marketplace </code></pre></div></div> <h3 id="团队配置">团队配置</h3> <p>在项目的 <code class="language-plaintext highlighter-rouge">.claude/settings.json</code> 中配置自动安装:</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"extraKnownMarketplaces"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"my-marketplace"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"source"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"source"</span><span class="p">:</span><span class="w"> </span><span class="s2">"github"</span><span class="p">,</span><span class="w"> </span><span class="nl">"repo"</span><span class="p">:</span><span class="w"> </span><span class="s2">"your-org/my-marketplace"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nl">"enabledPlugins"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"plugin-name@my-marketplace"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <p>团队成员信任仓库文件夹后,插件会自动安装。</p> <hr /> <h2 id="最佳实践">最佳实践</h2> <h3 id="安全性">安全性</h3> <ol> <li><strong>验证输入</strong>:永远不要盲目信任输入数据</li> <li><strong>引用变量</strong>:使用 <code class="language-plaintext highlighter-rouge">"$VAR"</code> 而不是 <code class="language-plaintext highlighter-rouge">$VAR</code></li> <li><strong>阻止路径遍历</strong>:检查文件路径中的 <code class="language-plaintext highlighter-rouge">..</code></li> <li><strong>使用绝对路径</strong>:为脚本指定完整路径</li> <li><strong>跳过敏感文件</strong>:避免处理 <code class="language-plaintext highlighter-rouge">.env</code>、<code class="language-plaintext highlighter-rouge">.git/</code>、密钥等</li> </ol> <h3 id="性能">性能</h3> <ol> <li><strong>设置超时</strong>:为长时间运行的脚本设置合理的超时</li> <li><strong>并行执行</strong>:多个匹配的 Hook 会并行运行</li> <li><strong>去重</strong>:相同的 Hook 命令会自动去重</li> </ol> <h3 id="调试">调试</h3> <ol> <li><strong>使用调试模式</strong>:<code class="language-plaintext highlighter-rouge">claude --debug</code> 查看详细执行信息</li> <li><strong>测试命令</strong>:先手动运行 Hook 命令确保正常工作</li> <li><strong>检查配置</strong>:使用 <code class="language-plaintext highlighter-rouge">/hooks</code> 查看已注册的 Hook</li> </ol> <hr /> <h2 id="总结">总结</h2> <p>Claude Code 的插件系统提供了强大的扩展能力:</p> <ul> <li><strong>Commands</strong>:快速创建自定义命令</li> <li><strong>Agents</strong>:定义专门的子代理</li> <li><strong>Skills</strong>:扩展模型能力</li> <li><strong>Hooks</strong>:自动化工作流和增强安全性</li> <li><strong>MCP Servers</strong>:集成外部工具</li> </ul> <p>通过插件系统,你可以:</p> <ul> <li>自动化重复任务</li> <li>增强开发安全性</li> <li>集成团队工具</li> <li>提升开发效率</li> </ul> <p>参考资源:</p> <ul> <li><a href="https://code.claude.com/docs">Claude Code 官方文档</a></li> <li><a href="https://github.com/discountry/ritmex-marketplace">ritmex-marketplace 示例</a></li> <li><a href="https://code.claude.com/docs/plugins-reference">Plugin 参考文档</a></li> <li><a href="https://code.claude.com/docs/hooks-reference">Hook 参考文档</a></li> </ul> <p>开始创建你的第一个插件,让 Claude Code 更加强大!</p>

2025/12/13
阅读更多

如何在手机上优雅地 Vibe Coding

<p>在手机上写代码的核心思路是: <strong>计算在远程,手机只负责输入与查看结果。</strong></p> <!--more--> <h1 id="方案一在-vps-上运行-codex--claude-code-等-cli">方案一:在 VPS 上运行 Codex / Claude Code 等 CLI</h1> <p>然后手机用 Termius(或任意 iOS SSH App)连接</p> <p>流程非常简单:</p> <ol> <li><strong>在 VPS 上安装 Node(18+)与 Coding CLI:</strong></li> </ol> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-fsSL</span> https://deb.nodesource.com/setup_20.x | <span class="nb">sudo</span> <span class="nt">-E</span> bash - <span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">-y</span> nodejs </code></pre></div></div> <p>安装 Codex 或其他 CLI:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm <span class="nb">install</span> <span class="nt">-g</span> @openai/codex </code></pre></div></div> <ol> <li><strong>在 VPS 上运行 CLI:</strong></li> </ol> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>codex </code></pre></div></div> <ol> <li><strong>手机端用 Termius 等 SSH App 登录 VPS。</strong> 进入终端后就能直接使用 CLI,在手机上写代码、跑 agent。</li> </ol> <p>特点:</p> <ul> <li>环境永远在线</li> <li>手机就是纯终端</li> <li>随时随地 vibe coding</li> </ul> <hr /> <h1 id="方案二使用-happy把家里电脑的-coding-cli-映射到手机">方案二:使用 Happy,把家里电脑的 Coding CLI 映射到手机</h1> <p>(官方 Quick Start 工作方式)</p> <p>Happy 的作用是: <strong>把你家里电脑正在运行的 coding CLI,安全地连接到你的手机上。</strong> 不需要公网 IP,也不需要 SSH。</p> <p>流程:</p> <ol> <li><strong>在家里电脑安装 Node(18+)与 Happy:</strong></li> </ol> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm <span class="nb">install</span> <span class="nt">-g</span> happy-coder </code></pre></div></div> <ol> <li><strong>在电脑执行认证:</strong></li> </ol> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>happy <span class="nt">--auth</span> </code></pre></div></div> <p>电脑会显示一个二维码 / 代码。</p> <ol> <li><strong>打开手机上的 Happy(App 或 Web)扫描绑定。</strong></li> </ol> <p>绑定后,你就能:</p> <ul> <li>在手机上访问电脑的 coding CLI</li> <li>操作完全在手机界面完成</li> <li>电脑执行、手机查看结果</li> </ul> <p>特点:</p> <ul> <li>复用家里电脑的性能与环境</li> <li>手机端操作舒服</li> <li>无需 SSH、无需对外暴露电脑</li> </ul> <h1 id="总结">总结</h1> <p>手机优雅 vibe coding 的最简单实践就是:</p> <ul> <li><strong>要稳定、常在线 → VPS + SSH 运行 Codex 等 CLI</strong></li> <li><strong>要高性能、用自己电脑 → Happy 远程连接本地 CLI</strong></li> </ul> <p>两种方式都足够轻量,也都能让手机实现完整 coding 体验。</p>

2025/12/9
阅读更多

买房时,我们到底在买什么?——中国住宅真实寿命研究报告

<p>过去三十年,房地产是中国家庭资产配置的绝对核心。在长期单边上涨的市场环境下,房产被视为唯一的低风险高收益资产,吸纳了居民部门绝大多数的储蓄与未来现金流。</p> <p>随着宏观经济进入调整期,资产价格预期的逆转迫使市场参与者重新评估其持有成本与潜在风险。当剥离了高增长时代的金融溢价后,一个长期被忽视的结构性风险暴露无遗:</p> <p>购房者通过背负长达 30 年的刚性债务,试图锁定 70 年的土地使用权。然而,作为权益载体的钢筋混凝土建筑,其统计学意义上的物理寿命,往往无法覆盖完整的产权周期,甚至难以跑赢按揭贷款的偿付周期。这种债务久期与资产寿命的倒挂,构成了普通家庭资产负债表上最大的隐患。</p> <!--more--> <h3 id="1-核心矛盾设计标准-vs-统计现实">1. 核心矛盾:设计标准 vs. 统计现实</h3> <p>关于房屋寿命,存在两个截然不同的概念:</p> <ul> <li><strong>设计使用年限(理论值)</strong>:指在正常设计、施工、使用和维护下,房屋结构能满足安全使用的年限。 <ul> <li>根据《建筑结构可靠度设计统一标准》(GB 50068-2001)和《民用建筑设计通则》(JGJ 37-1987),普通居住房屋的结构设计使用年限为 <strong>50年</strong>。</li> <li>重要建筑(如高层地标)可达 <strong>100年</strong>。</li> </ul> </li> <li><strong>实际服役寿命(统计值)</strong>:指房屋从建成到被拆除的实际时间。 <ul> <li>根据剑桥大学 Zhou 等人 2019 年发表于《Sustainability》的研究,通过对 1978-2017 年中国城市住宅存量的生存分析,得出中国城市住宅建筑的平均寿命约为 <strong>34.1年</strong>。</li> <li>这一数据验证了住建部原副部长仇保兴在 2010 年提出的观点:“我国建筑的平均寿命只能维持 <strong>25-30年</strong>。”</li> </ul> </li> </ul> <h3 id="2-寿命折损原因分析">2. 寿命折损原因分析</h3> <p>中国住宅“短命”并非单一结构质量问题,而是复合因素的结果:</p> <ul> <li><strong>非物理性折损(拆迁与更新)</strong>:这是导致平均寿命偏低的主因。在城市化快速推进阶段,许多房屋结构尚未老化,但因土地价值重估、城市规划变更或容积率调整而被提前拆除。</li> <li><strong>建造质量的历史包袱</strong>:上世纪 80-90 年代建造的早期商品房或房改房,受限于当时的建材标准(如预制板结构)和施工监管,耐久性确实不足,导致目前面临集中淘汰。</li> <li><strong>维护体系缺失</strong>:相比于建设阶段的巨额投入,国内住宅在交付后的维护投入长期不足。缺乏系统的修缮导致建筑老化速度加快,“年久失修”成为拆除的合理化理由。</li> </ul> <h3 id="3-一线城市的特殊性上海与北广深">3. 一线城市的特殊性:上海与北广深</h3> <p>对于一线城市(北上广深),情况较全国平均水平略有不同。</p> <ul> <li><strong>质量更优,寿命略长</strong>:一线城市执行更严格的建筑规范和监管。2024 年关于上海民用建筑全生命周期碳排放的研究指出,上海民用建筑的平均寿命约为 <strong>40年</strong>。这高于全国 34.1 年的平均水平。</li> <li><strong>更新压力依然存在</strong>:尽管建筑质量较好,但一线城市土地稀缺,旧城改造和城市更新的动力更强。许多位于核心地段的低密度老旧小区(如 6 层砖混楼),往往因无法匹配当前的土地经济价值而被拆除重建。</li> </ul> <p>对于一线城市购房者,<strong>30-40年</strong> 是一个基于历史数据的合理预期区间。特别是 2000 年之前建造的住宅,面临着更高的物理老化风险或拆迁不确定性。</p> <h3 id="4-国际横向对比">4. 国际横向对比</h3> <p>将视野扩大到全球,中国住宅的寿命处于什么水平?</p> <table> <thead> <tr> <th style="text-align: left">国家/地区</th> <th style="text-align: left">住宅平均寿命 (估算/统计)</th> <th style="text-align: left">主要特征</th> </tr> </thead> <tbody> <tr> <td style="text-align: left"><strong>中国</strong></td> <td style="text-align: left"><strong>25 - 35 年</strong></td> <td style="text-align: left">受城市更新和早期质量影响大,实际寿命远低于设计寿命。</td> </tr> <tr> <td style="text-align: left"><strong>日本</strong></td> <td style="text-align: left"><strong>25 - 35 年</strong></td> <td style="text-align: left">尽管建筑技术先进,但因资产折旧制度和对新房的偏好,市场倾向于“拆旧建新”,经济寿命短。</td> </tr> <tr> <td style="text-align: left"><strong>美国</strong></td> <td style="text-align: left"><strong>61 - 74 年</strong></td> <td style="text-align: left">存量房市场成熟,木结构房屋维护体系完善。</td> </tr> <tr> <td style="text-align: left"><strong>英国</strong></td> <td style="text-align: left"><strong>75 - 132 年</strong></td> <td style="text-align: left">极端案例。大量维多利亚时期砖石建筑仍在使用,社会习惯于修缮而非拆除。</td> </tr> <tr> <td style="text-align: left"><strong>西欧</strong></td> <td style="text-align: left"><strong>70 - 100 年</strong></td> <td style="text-align: left">普遍拥有较长的建筑服役周期。</td> </tr> </tbody> </table> <p><strong>数据来源</strong>:<em>Sustainability (MDPI)</em>, <em>ResearchGate</em>, <em>China Economic Review</em>, 英国 <em>BS 7543</em> 标准。</p> <h3 id="5-结语最大的赌场往往不需要门票">5. 结语:最大的赌场往往不需要门票</h3> <p>在二级市场,无论是股票还是加密货币,成熟的投资者都会反复告诫新人一条铁律:<strong>远离合约,拒绝高杠杆</strong>。因为在波动的市场中,加杠杆等同于将命运交付给概率,稍有不慎便是爆仓归零。</p> <p>然而,极具讽刺意味的是,在面对“买房”这一人生最大宗交易时,绝大多数以“稳健”自居的普通家庭,却毫不犹豫地选择了拉满杠杆、押上全部身家,进行一次长达 30 年的单边做多。</p> <p>这不仅是一次满仓梭哈,更是一场针对劣质资产的豪赌。我们用透支未来 30 年现金流的代价,去锁定一个统计寿命可能仅有 34 年、且并不具备神圣不可侵犯之私有产权属性的耗材。当按揭贷款的周期几乎等同于建筑物本身的物理生命周期时,这在金融逻辑上已经构成了一种极其危险的“久期错配”。</p> <p>在这个局中,人口老龄化是灰犀牛,建筑短命是黑天鹅,而产权的不确定性则是始终悬在头顶的达摩克利斯之剑。</p> <p>当下越来越多的年轻人选择不婚、不育、不买房,被主流舆论诟病为“躺平”或“缺乏责任感”。但若从投资风控的角度审视,这或许是新生代作为市场参与者,在直觉上察觉到了赔率的失衡——当一张期货合约的底层资产在不断折旧,且交割规则由庄家单方面解释时,<strong>拒绝开仓,才是唯一的理性避险。</strong></p>

2025/12/9
阅读更多

在 512MB 微型 VPS 上创建虚拟内存并安装 Codex

<p>在 512MB 甚至 256MB 这种微型 VPS 上跑现代工具(比如 <code class="language-plaintext highlighter-rouge">bun add</code>、<code class="language-plaintext highlighter-rouge">npm install</code>、Codex CLI)时,很容易遭遇内核 OOM(Out of Memory)直接把进程干掉:</p> <!--more--> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/usr/bin/env: ‘node’: No such file or directory Out of memory: Killed process ... </code></pre></div></div> <p>此类问题一般由两点引起:</p> <ol> <li><strong>系统没有 Node.js</strong></li> <li><strong>没有启用 swap,内存耗尽即被 OOM 干掉</strong></li> </ol> <p>以下内容提供清晰可靠的处理流程: (1)释放磁盘空间 →(2)创建并启用 1GB swap →(3)安装 Node.js 20(NodeSource)→(4)安装 Codex CLI 最后附带完整一键脚本。</p> <hr /> <h2 id="1-查看当前内存与-swap-状态">1. 查看当前内存与 swap 状态</h2> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>free <span class="nt">-h</span> swapon <span class="nt">--show</span> </code></pre></div></div> <p>典型输出(Swap 为 0B):</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Swap: 0B 0B 0B </code></pre></div></div> <p>必须先启用 swap 才能稳定运行安装工具。</p> <hr /> <h2 id="2-释放磁盘空间若--已满">2. 释放磁盘空间(若 / 已满)</h2> <p>检查磁盘:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">df</span> <span class="nt">-h</span> </code></pre></div></div> <p>若使用率100%,需要先清理:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo truncate</span> <span class="nt">-s</span> 0 /var/log/sing-box/access.log 2&gt;/dev/null <span class="o">||</span> <span class="nb">true sudo truncate</span> <span class="nt">-s</span> 0 /var/log/btmp.1 2&gt;/dev/null <span class="o">||</span> <span class="nb">true sudo </span>apt-get clean </code></pre></div></div> <p>再次确认:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">df</span> <span class="nt">-h</span> </code></pre></div></div> <hr /> <h2 id="3-创建并启用-1gb-swapfile">3. 创建并启用 1GB swapfile</h2> <h3 id="删除旧-swapfile如果有">删除旧 swapfile(如果有)</h3> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>swapoff /swapfile 2&gt;/dev/null <span class="o">||</span> <span class="nb">true sudo rm</span> <span class="nt">-f</span> /swapfile 2&gt;/dev/null <span class="o">||</span> <span class="nb">true</span> </code></pre></div></div> <h3 id="创建新-swapfile">创建新 swapfile</h3> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>fallocate <span class="nt">-l</span> 1G /swapfile <span class="nb">sudo chmod </span>600 /swapfile <span class="nb">sudo </span>mkswap /swapfile <span class="nb">sudo </span>swapon /swapfile </code></pre></div></div> <h3 id="检查-swap-是否生效">检查 swap 是否生效</h3> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>swapon <span class="nt">--show</span> free <span class="nt">-h</span> </code></pre></div></div> <p>应看到类似:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Swap: /swapfile file 1G 0B 1G </code></pre></div></div> <hr /> <h2 id="4-开机自动挂载-swap">4. 开机自动挂载 swap</h2> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="s1">'/swapfile none swap sw 0 0'</span> | <span class="nb">sudo tee</span> <span class="nt">-a</span> /etc/fstab </code></pre></div></div> <hr /> <h2 id="5-安装-nodejs-20nodesource-官方源">5. 安装 Node.js 20(NodeSource 官方源)</h2> <p>Codex CLI 基于 Node.js,因此必须先安装 Node.js。 使用 NodeSource 可获得最新稳定版本。</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-fsSL</span> https://deb.nodesource.com/setup_20.x | <span class="nb">sudo</span> <span class="nt">-E</span> bash - <span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">-y</span> nodejs </code></pre></div></div> <p>确认版本:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>node <span class="nt">-v</span> </code></pre></div></div> <hr /> <h2 id="6-安装-codex-cli">6. 安装 Codex CLI</h2> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>npm <span class="nb">install</span> <span class="nt">-g</span> @openai/codex </code></pre></div></div> <p>确认安装成功:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>which codex codex <span class="nt">--help</span> </code></pre></div></div> <p>若能正常输出帮助信息,则安装完成。</p> <hr /> <h1 id="一键脚本创建-swap--安装-nodejs20--安装-codex">一键脚本:创建 swap + 安装 Node.js20 + 安装 Codex</h1> <p>保存为 <code class="language-plaintext highlighter-rouge">setup_codex.sh</code>:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span> <span class="nb">set</span> <span class="nt">-e</span> <span class="nv">SWAP_SIZE</span><span class="o">=</span><span class="s2">"1G"</span> <span class="nb">echo</span> <span class="s2">"&gt;&gt;&gt; 清理日志与 APT 缓存"</span> <span class="nb">sudo truncate</span> <span class="nt">-s</span> 0 /var/log/sing-box/access.log 2&gt;/dev/null <span class="o">||</span> <span class="nb">true sudo truncate</span> <span class="nt">-s</span> 0 /var/log/btmp.1 2&gt;/dev/null <span class="o">||</span> <span class="nb">true sudo </span>apt-get clean <span class="o">||</span> <span class="nb">true echo</span> <span class="s2">"&gt;&gt;&gt; 删除旧 swapfile(如有)"</span> <span class="nb">sudo </span>swapoff /swapfile 2&gt;/dev/null <span class="o">||</span> <span class="nb">true sudo rm</span> <span class="nt">-f</span> /swapfile 2&gt;/dev/null <span class="o">||</span> <span class="nb">true echo</span> <span class="s2">"&gt;&gt;&gt; 创建新的 swapfile (</span><span class="k">${</span><span class="nv">SWAP_SIZE</span><span class="k">}</span><span class="s2">)"</span> <span class="nb">sudo </span>fallocate <span class="nt">-l</span> <span class="s2">"</span><span class="k">${</span><span class="nv">SWAP_SIZE</span><span class="k">}</span><span class="s2">"</span> /swapfile <span class="nb">sudo chmod </span>600 /swapfile <span class="nb">sudo </span>mkswap /swapfile <span class="nb">sudo </span>swapon /swapfile <span class="nb">echo</span> <span class="s2">"&gt;&gt;&gt; 写入 /etc/fstab(如果缺失)"</span> <span class="nv">FSTAB_LINE</span><span class="o">=</span><span class="s2">"/swapfile none swap sw 0 0"</span> <span class="k">if</span> <span class="o">!</span> <span class="nb">grep</span> <span class="nt">-q</span> <span class="s2">"^/swapfile "</span> /etc/fstab 2&gt;/dev/null<span class="p">;</span> <span class="k">then </span><span class="nb">echo</span> <span class="s2">"</span><span class="k">${</span><span class="nv">FSTAB_LINE</span><span class="k">}</span><span class="s2">"</span> | <span class="nb">sudo tee</span> <span class="nt">-a</span> /etc/fstab <span class="o">&gt;</span>/dev/null <span class="k">fi </span><span class="nb">echo</span> <span class="s2">"&gt;&gt;&gt; 安装 Node.js 20(NodeSource)"</span> curl <span class="nt">-fsSL</span> https://deb.nodesource.com/setup_20.x | <span class="nb">sudo</span> <span class="nt">-E</span> bash - <span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">-y</span> nodejs <span class="nb">echo</span> <span class="s2">"&gt;&gt;&gt; Node 版本:"</span> node <span class="nt">-v</span> <span class="nb">echo</span> <span class="s2">"&gt;&gt;&gt; 安装 Codex CLI"</span> <span class="nb">sudo </span>npm <span class="nb">install</span> <span class="nt">-g</span> @openai/codex <span class="nb">echo</span> <span class="s2">"&gt;&gt;&gt; Codex CLI 已安装"</span> which codex <span class="o">||</span> <span class="nb">true </span>codex <span class="nt">--help</span> <span class="o">||</span> <span class="nb">true echo</span> <span class="s2">"&gt;&gt;&gt; 完成"</span> free <span class="nt">-h</span> swapon <span class="nt">--show</span> </code></pre></div></div> <p>运行:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">chmod</span> +x setup_codex.sh ./setup_codex.sh </code></pre></div></div> <p>微型 VPS 上运行 Codex CLI 至此即可稳定运行,不再遇到 OOM Killed 或 node 不存在的问题。</p> <hr /> <p>如需我为你的服务器环境进一步优化配置,也可继续发我 <code class="language-plaintext highlighter-rouge">df -h</code>、<code class="language-plaintext highlighter-rouge">free -h</code>、<code class="language-plaintext highlighter-rouge">top</code> 等输出。</p>

2025/12/9
阅读更多

设计灵感网站推荐合集

<p>在进行网站设计、界面 UI/UX 创作或品牌营销页开发时,拥有一个优质的灵感库至关重要。下面我整理了一批极具参考价值的设计展示网站,涵盖一页式 (One-Page) 设计、Landing Page 范例、动画与微交互动效、作品集、创意图库等多个维度。无论你是「小恐龙 KOL tweet 模板」「社区互动页」「区块链/AI 项目官网」等场景,都能从中找到有助于提炼风格、调色板、布局结构或动画节奏的参考。</p> <!--more--> <h2 id="1-siteinspire">1. <a href="https://www.siteinspire.com/">siteInspire</a></h2> <p>这是一个专门展示优质网页设计的网站,其定位是「展示网络上最好的设计 + 才能」。:contentReference[oaicite:0]{index=0}<br /> <strong>推荐理由</strong>:</p> <ul> <li>涵盖了视觉、界面、交互佳作,适合做整体版式、配色与排版灵感采集。</li> <li>策展质量高,适合快速 « 浏览 + 收藏 »。<br /> <strong>使用建议</strong>:在构思品牌主页或大型项目官网(如你在 crypto/AI 生态中的各类主题页面)时,可先浏览 siteInspire ,锁定主视觉风格,再延伸开发。</li> </ul> <hr /> <h2 id="2-awwwards">2. <a href="https://www.awwwards.com/">Awwwards</a></h2> <p>这是一个全球知名的网页设计奖项平台,聚焦展示开发者、设计师、网页机构的高水准作品。:contentReference[oaicite:1]{index=1}<br /> <strong>推荐理由</strong>:</p> <ul> <li>包含「Site of the Day」「Nominees」「Winners」等分类,可看到当下最新最前沿的网页互动、动画技术、案例趋势。</li> <li>拥有按技术、类别筛选(如 React 、WebGL 、3D 、Scroll 等)功能。<br /> <strong>使用建议</strong>:如果你想让「小恐龙 &amp; 蟹王」那种角色动画在网页中有炫酷交互,或想做一个区块链项目页带微交互、3D 效果,这里是寻找技术灵感的极佳来源。</li> </ul> <hr /> <h2 id="3-css-design-awards">3. <a href="https://www.cssdesignawards.com/">CSS Design Awards</a></h2> <p>另一个高质量的网站奖项平台,强调 UI、UX 与创新三个维度。:contentReference[oaicite:2]{index=2}<br /> <strong>推荐理由</strong>:</p> <ul> <li>每个获奖作品都会标注 UI 、UX 、Innovation 评分,便于理解为何被评为佳作。</li> <li>可看到许多细节设计(排版、色彩、微动效)值得借鉴。<br /> <strong>使用建议</strong>:适用于你在制作 newsletter、Landing Page、社群宣传页 (如 Wind Runner SBT、YieldBasis allocation letter) 时,用于参考「优秀互动+体验」的结构。</li> </ul> <hr /> <h2 id="4-one-page-love">4. <a href="https://onepagelove.com/">One Page Love</a></h2> <p>专注于单页网站(One-Page)设计的灵感库。:contentReference[oaicite:3]{index=3}<br /> <strong>推荐理由</strong>:</p> <ul> <li>集合了大量单页网站案例、模板与资源,非常适合快速部署或构思一页式页面。</li> <li>模板、资源链接丰富,可作为启动项目参考。<br /> <strong>使用建议</strong>:如果你准备做一个「小恐龙 快报 #1」那种一页式宣传页,或者 crypto 空投活动页面、SBT 活动页面,这里可以先选一个布局,再调整品牌角色(小恐龙/蟹王等)、色彩、图像场景。</li> </ul> <hr /> <h2 id="5-landinglove">5. <a href="https://www.landing.love/">Landing.love</a></h2> <p>(你提供的 Landing.love 链接)这个站点专注于 Landing Page 设计灵感。<br /> <strong>推荐理由</strong>:</p> <ul> <li>虽不像其他奖项平台那样广为熟知,但专注在 Landing Page 范畴,可直接找到转化型页面结构的参考。<br /> <strong>使用建议</strong>:当你需要一个「注册/领取/参与」型页面时,此站可帮助你快速选定 Hero 区、 CTA 按钮位置、视觉聚焦等结构方案。</li> </ul> <hr /> <h2 id="6-landingfolio">6. <a href="https://www.landingfolio.com/">Landingfolio</a></h2> <p>专门为 Landing Page 提供灵感、模板与组件库。:contentReference[oaicite:4]{index=4}<br /> <strong>推荐理由</strong>:</p> <ul> <li>不仅有案例,还有可复用的组件(Tailwind、Webflow、Figma)和模板。</li> <li>分类细致(如 SaaS、产品、AI、加密、企业等)且资源丰富。<br /> <strong>使用建议</strong>:适合当你做「Kite AI Wind Runner SBT 宣页」或「Sentient Library 活动页」等具备 CTA 、注册流程、限时优惠结构的页面时使用。你甚至可以直接借用组件+模板,加快开发流程。</li> </ul> <hr /> <h2 id="7-wall-of-portfolios">7. <a href="https://www.wallofportfolios.in/">Wall of Portfolios</a></h2> <p>聚焦作品集类网页展示的灵感集合。<br /> <strong>推荐理由</strong>:</p> <ul> <li>当你需要做个人/团队 portfolio 页(例如你自己做 Web3 工具、AI 代理系统的展示页)时,这是一个不错的参考库。<br /> <strong>使用建议</strong>:建议浏览那些由设计师、创意工作室打造的「作品展示页」结构,借鉴 项目模块布局、案例 Thumbnail 布局、动画切换方式,再结合你品牌吉祥物“小恐龙”等角色元素。</li> </ul> <hr /> <h2 id="8-ui-ux-showcase">8. <a href="https://uiuxshowcase.com/">UI UX Showcase</a></h2> <p>专注于 UI/UX 与设计资源展示的站点。:contentReference[oaicite:5]{index=5}<br /> <strong>推荐理由</strong>:</p> <ul> <li>除了网页设计,还有设计资源、AI 工具推荐,非常适合追求 UX 细节与工具效率的你。<br /> <strong>使用建议</strong>:你可以用它来找到微动效、界面组件、流程设计灵感。当你做「小恐龙 &amp; Monkey 驾驶 Zama Car」那种场景动画/界面演示页时,借鉴 UI /UX 细节会更加出彩。</li> </ul> <hr /> <h2 id="9-httpster">9. <a href="https://httpster.net/">Httpster</a></h2> <p>一个手工精选、不追大奖但追设计态度的网页设计展示网。:contentReference[oaicite:6]{index=6}<br /> <strong>推荐理由</strong>:</p> <ul> <li>风格偏向极简、排版大胆、实验性强,很适合从中挖掘另类布局或打破常规的设计思路。<br /> <strong>使用建议</strong>:当你想让页面更具特色、更有“创意视觉冲击”时(比如 “Sentient Library” 场景页、或 “Cysic Mining Site” 互动页),在 Httpster 找灵感会很合适。</li> </ul> <hr /> <h2 id="10-designspiration">10. <a href="https://www.designspiration.com/">Designspiration</a></h2> <p>一个广泛的视觉灵感平台,涵盖色彩、图像、排版、插画等。<br /> <strong>推荐理由</strong>:</p> <ul> <li>虽不专门针对网页,但在找色彩组合、插画风格、品牌配色 palette 时非常有用。<br /> <strong>使用建议</strong>:你可将其用于“小恐龙 + 蟹王 + 熊猫 + 小猪”角色画面中的配色参考,或寻找背景插画风格、叙事图像组合,再在网页中加以延伸。</li> </ul> <hr /> <h2 id="11-abduzeedo">11. <a href="https://abduzeedo.com/">Abduzeedo</a></h2> <p>一个创意设计博客与视觉灵感分享平台。<br /> <strong>推荐理由</strong>:</p> <ul> <li>包含设计师访谈、教程、灵感汇总。适合你在品牌视觉、角色插画、小恐龙场景扩展中寻找更丰富的来源。<br /> <strong>使用建议</strong>:当你做“御花园 Portaltobitcoin 茶话会”那种叙事场景时,可借助 Abduzeedo 查找插画风格、排版摆设、空间构图等灵感。</li> </ul> <hr /> <h2 id="12-gsap-showcase">12. <a href="https://gsap.com/showcase/">GSAP Showcase</a></h2> <p>由 GSAP(GreenSock Animation Platform)官方维护的动画网页精选合集。:contentReference[oaicite:8]{index=8}<br /> <strong>推荐理由</strong>:</p> <ul> <li>专注于动效、微交互、滚动触发、SVG 动画等高级交互形式。</li> <li>若你网页中有「小恐龙 grid 交易在迪拜」「小恐龙 &amp; 猴子 驾驶 Zama Car」这样的动态叙事场景,这类示例极具参考价值。<br /> <strong>使用建议</strong>:建议浏览其 Showcase 中发现哪种动画触发方式(如 ScrollTrigger、MorphSVG、Inertia)适合你的场景,再在项目中复用或改造。</li> </ul> <hr /> <h2 id="13-behance">13. <a href="https://www.behance.net/">Behance</a></h2> <p>由 Behance 提供的全球创意作品集平台。<br /> <strong>推荐理由</strong>:</p> <ul> <li>设计师、插画师、动效师、网页开发者大量作品集中地,适合探索「概念页」「完整项目展示」的视觉叙事方式。<br /> <strong>使用建议</strong>:你可以搜索关键词如 “web design crypto”, “landing page illustration”, “UI/UX animation”,看看别人如何将角色、叙事、品牌融合到网页设计中,从中提炼灵感再落地至你的 Web3/AI 生态页面。</li> </ul> <hr /> <h2 id="14-dribbble">14. <a href="https://dribbble.com/">Dribbble</a></h2> <p>由 Dribbble 提供的设计师作品分享平台。<br /> <strong>推荐理由</strong>:</p> <ul> <li>微交互、界面细节、动效 Preview 图常见;适合快速捕捉「一个按钮 hover 动画」「One-Page 滑动效果」这类设计元素。<br /> <strong>使用建议</strong>:当你在做页面细节(如 “小恐龙 &amp; 猴子 驾驶 Zama Car”的按钮/切换/视觉反馈)时,Dribbble 是查找 UI 元素动效的绝佳场所,可供快速 slice 与复用。</li> </ul> <hr /> <h1 id="-总结">📌 总结</h1> <ul> <li>如果你需要 <strong>整体版式+版面灵感</strong>:推荐 siteInspire、Httpster、Designspiration。</li> <li>想看 <strong>获奖/前沿交互效果</strong>:推荐 Awwwards、CSS Design Awards、GSAP Showcase。</li> <li>需要 <strong>一页式或 Landing Page 结构参考</strong>:推荐 One Page Love、Landing.love、Landingfolio。</li> <li>做 <strong>作品集/品牌展示页</strong>:推荐 Wall of Portfolios、Behance、Dribbble。</li> <li>想丰富 <strong>插画/视觉风格/配色</strong>:推荐 Abduzeedo、Designspiration。</li> <li>想搜寻 <strong>UI/UX 组件/动效资源</strong>:推荐 UI UX Showcase、Dribbble。</li> </ul> <p>在你下一次打造「小恐龙 KOL tweet 模板」「社区互动页」「AI 代理支付系统的Landing Page」的时候,不妨按照以下流程使用这些资源:</p> <ol> <li>先从整体风格库(如 siteInspire、Httpster)中选出一个视觉方向。</li> <li>再去 Landing/One-Page 站点(如 Landingfolio、One Page Love)锁定结构布局。</li> <li>从交互/动画库(如 GSAP Showcase、Awwwards)选取可复用的动效方案。</li> <li>最后去插画/视觉/组件站点(如 Designspiration、UI UX Showcase)提取角色、配色、按钮、组件样式。</li> <li>汇总后结合你品牌中“小恐龙、小猪、蟹王、熊猫”等角色与 ARB/Zama/Sentient/Billions Logo 元素,融入场景叙事,再做 Tailwind CSS/React/Vite 或 Webflow 落地。</li> </ol> <p>希望这份集合对你接下来的网页设计与品牌传播创作有所帮助!如果你想我帮你从其中任意一个站点摘出 <strong>10 个精选案例</strong>(比如「区块链项目专用Landing Page」)并生成 Figma 链接或 Tailwind 组件,也可以告诉我,我可以继续帮你整理。</p>

2025/11/20
阅读更多

灵感菇——ChromeAI增强插件

<p>链接直达:<a href="https://chromewebstore.google.com/detail/mjbnaihbmfffiboanaecmeipafliekkn">灵感菇AI助手</a></p> <!--more--> <p>更新Chrome到最新版本</p> <p>Chrome浏览器地址栏输入</p> <p><a href="chrome://flags/#prompt-api-for-gemini-nano">chrome://flags/#prompt-api-for-gemini-nano</a></p> <p>修改为 <code class="language-plaintext highlighter-rouge">Enabled</code></p> <p>前往Chrome应用商店</p> <p><a href="https://chromewebstore.google.com/detail/mjbnaihbmfffiboanaecmeipafliekkn">https://chromewebstore.google.com/detail/mjbnaihbmfffiboanaecmeipafliekkn</a></p> <p>下载安装后在右上角插件设置固定灵感菇插件</p> <p>点击打开插件设置页面,触发Chrome内置AI模型加载</p> <p>加载完毕后刷新 X 等网站即可看到AI增强功能</p>

2025/10/31
阅读更多

使用 Warp 拯救 VPS 解锁 ChatGPT/Gemini/Netflix/Google验证码

<p>用了很久的 VPS 突然打不开 Gemini 了,虽然是日本 IP 但是显示服务尚未在当前地区开放。</p> <p>真实物理IP/静态住宅IP是比较贵的,那么有没有一种办法可以解除这些限制呢?</p> <!--more--> <p>今天学习到了可以使用 Cloudflare 提供的免费 Warp 服务,为 VPS 服务器本身添加代理网络出口,达到解锁目的。</p> <p>具体使用到的是<a href="https://github.com/yonggekkk/warp-yg">warp-yg</a>一键安装脚本。</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bash &lt;<span class="o">(</span>curl <span class="nt">-Ls</span> https://raw.githubusercontent.com/yonggekkk/warp-yg/main/CFwarp.sh<span class="o">)</span> </code></pre></div></div> <p>根据命令行的提示操作即可。</p>

2025/9/4
阅读更多

在末法时代里爬行

<p>2002年,《波士顿环球报》揭露波士顿1500名神父中,有249名涉嫌性侵儿童。其中恶名昭著的吉欧根神父,面临130项性侵指控。</p> <p>该调查过程于2015年被改编为电影《聚焦》(Spotlight)。</p> <!--more--> <p>同年7月26日,中国互联网出现署名“释正义”的举报帖《少林寺方丈释永信这只大老虎,谁来监督》,指控释永信拥有双重户籍、强奸尼僧释延果、包养情妇,并与哈尔滨女子关丽丽、尼僧释延洁各育有一名私生女,并提供了相关证据。</p> <p>2015年11月,河南调查组公布初步结果:释永信无私生子女,方丈资格“程序合法合规”;其余被举报问题仍在依法调查中。</p> <hr /> <p>释永信(原名刘应成),1965年9月6日生,八字乙巳 甲申 癸亥。2025年恰逢其转入戊寅大运,命理上讲,叫做「伤官见官」,主诉讼牢狱之灾。</p> <p>2025年7月27日,少林寺管理处官方通报:释永信涉嫌刑事犯罪,挪用侵占项目资金及寺院资产;严重违反佛教戒律,长期与多名女性保持不正当关系并育有私生子。</p> <p>7月28日,中国佛教协会公告,同意注销释永信戒牒。</p> <hr /> <p>佛教典籍载:佛法流传世间共一万二千年,分正法一千年、像法一千年、末法一万年。<br /> 正法为真佛法,像法尚存佛法之形,末法则佛法几近消亡。</p> <p>佛陀涅槃前三月,于《法灭尽经》中预言末世景象:</p> <blockquote> <p>“吾涅槃后,法欲灭时,五逆浊世,魔道兴盛。<br /> 魔作沙门,坏乱吾道,著俗衣裳,乐好袈裟,五色之服,饮酒啖肉,杀生贪味。<br /> 无有慈心,更相憎嫉。”</p> </blockquote> <p>佛陀早已预言将有魔道假扮僧人,败坏佛法,行龌龊之事。</p> <p>同时预言:末法时代,纵有真修行者舍己为人,亦会遭假僧诽谤驱逐。<br /> 寺庙终将荒废,僧人腐化,贪财淫乱,不分男女,无人持戒诵经。</p> <p>以佛灭度年(公元前543年)为基准,2025年已入末法时代69年。<br /> 对照当下新闻与佛陀预言,世人皆可自忖:剧情已演进至哪一章节。</p> <hr /> <blockquote> <p>每只蚂蚁 都有眼睛鼻子 它美不美丽 偏差有没有一毫厘 有何关系</p> <p>每一个人 伤心了就哭泣 饿了就要吃 相差大不过天地 有何刺激</p> <p>有太多太多魔力 太少道理 太多太多游戏 只是为了好奇<br /> 还有什么值得 歇斯底里 对什么东西 死心塌地</p> <p>一个一个偶像 都不外如此 沉迷过的偶像 一个个消失</p> <p>谁曾伤天害理 谁又是上帝 我们在等待 什么奇迹</p> <p>最后剩下自己 舍不得挑剔 最后对着自己 也不大看得起<br /> 谁给我全世界 我都会怀疑 心花怒放 却开到荼蘼</p> </blockquote>

2025/8/24
阅读更多

Hysteria2 拯救 AWS lightsail 极速科学上网

<p>以前我使用的上网冲浪方案都是 v2ray Websocket(WS)+TLS+CDN 的方式,这种方式的好处是安全性高,保护服务器不被 ban</p> <p>但前几天日本和新加坡的线路直接卡成💩</p> <p>多年没有研究上网冲浪姿势的我,只好重新拿起课本</p> <p>经过一番学习之后,我了解到了宝藏协议 Hysteria2</p> <!--more--> <p>Hysteria2 底层使用的是 UDP 协议,即使 TCP ping 服务器有 200-300ms 的延迟</p> <p>使用 UDP 也能将延迟干到 50ms 左右</p> <p>网速更是可以快到运营商想来ban你的UDP流量</p> <p>Youtube 8K 视频也能做到秒开不卡顿</p> <p>使用 <a href="https://lightsail.aws.amazon.com/">AWS Lightsail</a> 的好处是</p> <p>我可以很放心地把一些需要长期保存和稳定运行的服务都跑在上面</p> <p>也可以安心地存放一些 API Key 和密钥之类的</p> <p>网上大把的野鸡运营商的服务器,我是什么都不敢保存的</p> <h3 id="安装教程">安装教程</h3> <p><a href="https://v2.hysteria.network/zh/docs/getting-started/Server-Installation-Script/">Hysteria2 官网</a> 贴心地提供了一键安装脚本</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 安装</span> bash &lt;<span class="o">(</span>curl <span class="nt">-fsSL</span> https://get.hy2.sh/<span class="o">)</span> <span class="c"># 删除</span> bash &lt;<span class="o">(</span>curl <span class="nt">-fsSL</span> https://get.hy2.sh/<span class="o">)</span> <span class="nt">--remove</span> </code></pre></div></div> <p><strong>编辑配置</strong></p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vim /etc/hysteria/config.yaml </code></pre></div></div> <p><strong>配置内容</strong></p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>listen: :443 # 服务端口,可以换成别的 acme: domains: - hysteria.example.com # 你的域名 email: admin@example.com # 你的邮箱 type: dns dns: name: cloudflare config: cloudflare_api_token: vRDNxxxxxxxxxxxxxxx # Cloudflare API Key auth: type: password password: 123456789 # 密码 masquerade: type: proxy proxy: url: https://bing.com/ rewriteHost: true </code></pre></div></div> <p><strong>启动服务</strong></p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl <span class="nb">enable</span> <span class="nt">--now</span> hysteria-server.service <span class="c"># 查看状态</span> systemctl status hysteria-server.service <span class="c"># 查看日志</span> journalctl <span class="nt">--no-pager</span> <span class="nt">-e</span> <span class="nt">-u</span> hysteria-server.service </code></pre></div></div> <p>到这一步就大功告成了!</p> <p>当然 Hysteria 也不是没有缺点,UDP的速度快是快,但很容易丢包和断流,不过对于90%使用场景是看网页刷视频的朋友,极速的体验还是非常舒服的。</p>

2025/6/11
阅读更多