PageSourceSearch

https://blog.1874.cool/hermes-update-fork/

html 1874.cool collected 2026-10-03 20:25:41 UTC 31,685 bytes, 94 lines download raw bytes

1<!DOCTYPE html><html lang="zh-Hans"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>无需打散件补丁:用 fork 接管 Hermes 更新 • 1874&#39;s BLOG</title><link rel="icon" href="/favicon.ico" sizes="any"><link rel="icon" href="/icon.svg" type="image/svg+xml"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="manifest" href="/manifest.webmanifest"><link rel="canonical" href="https://blog.1874.cool/hermes-update-fork/"><link rel="alternate" type="text/markdown" href="https://blog.1874.cool/hermes-update-fork.md"><link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css" rel="stylesheet"><meta name="title" content="无需打散件补丁:用 fork 接管 Hermes 更新 • 1874's BLOG"><meta name="description" content="通过将 Hermes 的 origin remote 指向个人 fork,并创建 .skip_upstream_prompt 静音文件,可让 hermes update 从 fork 拉取代码,实现安全的更新与补丁开发流程;同时可自行设置 upstream 同步官方仓库,保持 fork 与上游代码同步,简化开发、合并和部署步骤。"><meta name="author" content="1874"><meta name="theme-color" content=""><meta property="og:type" content="article"><meta property="og:title" content="无需打散件补丁:用 fork 接管 Hermes 更新"><meta property="og:description" content="通过将 Hermes 的 origin remote 指向个人 fork,并创建 .skip_upstream_prompt 静音文件,可让 hermes update 从 fork 拉取代码,实现安全的更新与补丁开发流程;同时可自行设置 upstream 同步官方仓库,保持 fork 与上游代码同步,简化开发、合并和部署步骤。"><meta property="og:url" content="https://blog.1874.cool/hermes-update-fork/"><meta property="og:site_name" content="1874's BLOG"><meta property="og:locale" content="zh_Hans_CN"><!--<meta property="og:image" content={socialImageURL} />--><meta property="og:image:width" content="1200"><meta property="og:image:height" content="630"><meta property="article:author" content="1874"><meta property="article:published_time" content="2026-07-01T06:56:00.000Z"><meta property="twitter:card" content="summary_large_image"><meta property="twitter:url" content="https://blog.1874.cool/hermes-update-fork/"><meta property="twitter:title" content="无需打散件补丁:用 fork 接管 Hermes 更新"><meta property="twitter:description" content="通过将 Hermes 的 origin remote 指向个人 fork,并创建 .skip_upstream_prompt 静音文件,可让 hermes update 从 fork 拉取代码,实现安全的更新与补丁开发流程;同时可自行设置 upstream 同步官方仓库,保持 fork 与上游代码同步,简化开发、合并和部署步骤。"><!--<meta property="twitter:image" content={socialImageURL} />--><link rel="sitemap" href="/sitemap-index.xml"><link rel="alternate" type="application/rss+xml" title="1874's BLOG" href="/rss.xml"><meta name="generator" content="Astro v7.0.6"><link rel="stylesheet" href="/_astro/Base.CplzDdJP.css">
1<script type="module" src="/_astro/page.DpeqpYo8.js"></script>
1</head><body>
1<script>
2	const lightModePref = window.matchMedia("(prefers-color-scheme: light)");
3
4	function getUserPref() {
5		const storedTheme = typeof localStorage !== "undefined" && localStorage.getItem("theme");
6		return storedTheme || (lightModePref.matches ? "light" : "dark");
7	}
8
9	function setTheme(newTheme) {
10		if (newTheme !== "light" && newTheme !== "dark") {
11			return console.warn(
12				`Invalid theme value '${newTheme}' received. Expected 'light' or 'dark'.`,
13			);
14		}
15
16		const root = document.documentElement;
17
18		// root already set to newTheme, exit early
19		if (newTheme === root.getAttribute("data-theme")) {
20			return;
21		}
22
23		root.setAttribute("data-theme", newTheme);
24
25		const colorThemeMetaTag = document.querySelector("meta[name='theme-color']");
26		const bgColour = getComputedStyle(document.body).getPropertyValue("--theme-bg");
27		colorThemeMetaTag.setAttribute("content", `hsl(${bgColour})`);
28		if (typeof localStorage !== "undefined") {
29			localStorage.setItem("theme", newTheme);
30		}
31	}
32
33	// initial setup
34	setTheme(getUserPref());
35
36	// View Transitions hook to restore theme
37	document.addEventListener("astro:after-swap", () => setTheme(getUserPref()));
38
39	// listen for theme-change custom event, fired in src/components/ThemeToggle.astro
40	document.addEventListener("theme-change", (e) => {
41		setTheme(e.detail.theme);
42	});
43
44	// listen for prefers-color-scheme change.
45	lightModePref.addEventListener("change", (e) => setTheme(e.matches ? "light" : "dark"));
46</script>
46<a href="#main" class="sr-only focus:not-sr-only focus:fixed focus:start-1 focus:top-1.5">skip to content</a><header id="main-header" class="group relative mb-20 flex items-center sm:ps-[5rem]"><div class="flex sm:flex-col"><a href="/" class="inline-flex items-center sm:relative sm:inline-block" aria-current="false"><img src="/_astro/blog.6Wp_r5Mf.png" alt="logo" id="logo" width="64" height="64" class="object-cover me-3 sm:absolute sm:start-[-5rem] sm:me-0 " loading="eager" fetchpriority="high"><!--TODO 博客 Logo SVG--><span class="text-xl font-bold sm:text-2xl">1874</span></a><nav id="navigation-menu" class="absolute -inset-x-4 top-14 hidden flex-col items-end gap-y-4 rounded-md bg-bgColor/[.85] py-4 text-accent shadow backdrop-blur group-[.menu-open]:z-50 group-[.menu-open]:flex sm:static sm:z-auto sm:-ms-4 sm:mt-1 sm:flex sm:flex-row sm:items-center sm:divide-x sm:divide-dashed sm:divide-accent sm:rounded-none sm:bg-transparent sm:py-0 sm:shadow-none sm:backdrop-blur-none" aria-label="Main menu"><a href="/" class="px-4 py-4 sm:py-0 sm:hover:underline" aria-current="false" data-astro-prefetch>首页</a><a href="/tags/vibecoding" class="px-4 py-4 sm:py-0 sm:hover:underline" aria-current="false" data-astro-prefetch>VibeCoding</a><a href="/tags/赛博空间" class="px-4 py-4 sm:py-0 sm:hover:underline" aria-current="false" data-astro-prefetch>赛博空间</a><a href="/tags/代码之外" class="px-4 py-4 sm:py-0 sm:hover:underline" aria-current="false" data-astro-prefetch>代码之外</a><a href="/about" class="px-4 py-4 sm:py-0 sm:hover:underline" aria-current="false" data-astro-prefetch>关于</a><a href="/links" class="px-4 py-4 sm:py-0 sm:hover:underline" aria-current="false" data-astro-prefetch>友链</a></nav></div><site-search id="search" class="ms-auto" data-astro-cid-ac66eqjo="true"><button data-open-modal disabled class="flex h-9 w-9 items-center justify-center rounded-md ring-zinc-400 transition-all hover:ring-2" data-astro-cid-ac66eqjo><svg aria-label="search" class="h-7 w-7" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" data-astro-cid-ac66eqjo><path stroke="none" d="M0 0h24v24H0z" data-astro-cid-ac66eqjo></path><path d="M3 10a7 7 0 1 0 14 0 7 7 0 1 0-14 0M21 21l-6-6" data-astro-cid-ac66eqjo></path></svg></button><dialog aria-label="search" class="h-full max-h-full w-full max-w-full border border-zinc-400 bg-bgColor shadow backdrop:backdrop-blur sm:mx-auto sm:mb-auto sm:mt-16 sm:h-max sm:max-h-[calc(100%-8rem)] sm:min-h-[15rem] sm:w-5/6 sm:max-w-[48rem] sm:rounded-md" data-astro-cid-ac66eqjo><div class="dialog-frame flex flex-col gap-4 p-6 pt-12 sm:pt-6" data-astro-cid-ac66eqjo><button data-close-modal class="ms-auto cursor-pointer rounded-md bg-zinc-200 p-2 font-semibold dark:bg-zinc-700" data-astro-cid-ac66eqjo>Close</button><div class="search-container" data-astro-cid-ac66eqjo><div id="cactus__search" data-astro-cid-ac66eqjo></div></div></div></dialog></site-search>
46<script type="module" src="/_astro/Search.astro_astro_type_script_index_0_lang.DZAxRrEu.js"></script>
46<theme-toggle class="ms-2 sm:ms-4"><button id="theme-btn" type="button" class="relative h-9 w-9 rounded-md p-2 ring-zinc-400 transition-all hover:ring-2"><span class="sr-only">Dark Theme</span><svg id="sun-svg" class="absolute start-1/2 top-1/2 h-7 w-7 -translate-x-1/2 -translate-y-1/2 scale-100 opacity-100 transition-all dark:scale-0 dark:opacity-0" aria-hidden="true" focusable="false" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 18C15.3137 18 18 15.3137 18 12C18 8.68629 15.3137 6 12 6C8.68629 6 6 8.68629 6 12C6 15.3137 8.68629 18 12 18Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M22 12L23 12" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 2V1" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 23V22" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M20 20L19 19" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M20 4L19 5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M4 20L5 19" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M4 4L5 5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M1 12L2 12" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg><svg id="moon-svg" class="absolute start-1/2 top-1/2 h-7 w-7 -translate-x-1/2 -translate-y-1/2 scale-0 opacity-0 transition-all dark:scale-100 dark:opacity-100" aria-hidden="true" focusable="false" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path><path d="M17 4a2 2 0 0 0 2 2a2 2 0 0 0 -2 2a2 2 0 0 0 -2 -2a2 2 0 0 0 2 -2"></path><path d="M19 11h2m-1 -1v2"></path></svg></button></theme-toggle>
46<script type="module" src="/_astro/ThemeToggle.astro_astro_type_script_index_0_lang.BvRK_64s.js"></script>
46<mobile-button><button id="toggle-navigation-menu" class="group relative ms-4 h-7 w-7 sm:invisible sm:hidden" type="button" aria-label="Open main menu" aria-expanded="false" aria-haspopup="menu"><svg id="line-svg" class="absolute start-1/2 top-1/2 h-full w-full -translate-x-1/2 -translate-y-1/2 transition-all group-aria-expanded:scale-0 group-aria-expanded:opacity-0" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 9h16.5m-16.5 6.75h16.5"></path></svg><svg id="cross-svg" class="absolute text-accent start-1/2 top-1/2 h-full w-full -translate-x-1/2 -translate-y-1/2 scale-0 text-accent opacity-0 transition-all group-aria-expanded:scale-100 group-aria-expanded:opacity-100" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path></svg></button></mobile-button></header>
46<script type="module" src="/_astro/Header.astro_astro_type_script_index_0_lang.Bwcl6zRD.js"></script>
46<main id="main"><div class="post-layout gap-x-10 xl:flex xl:items-start"><aside class="sticky top-20 order-2 hidden max-h-[calc(100vh-6rem)] shrink-0 basis-64 overflow-y-auto xl:block"><h2 class="font-semibold">Table of Contents</h2><ul class="mt-4 text-xs"><li class><a class="block line-clamp-2 hover:text-accent mt-3" href="#前言" aria-label="Scroll to section: 前言"><span class="me-0.5">#</span>前言</a></li><li class><a class="block line-clamp-2 hover:text-accent mt-3" href="#核心判断" aria-label="Scroll to section: 核心判断"><span class="me-0.5">#</span>核心判断</a><ul><li class="ms-2"><a class="block line-clamp-2 hover:text-accent mt-2 text-[0.6875rem]" href="#fork-检测静音" aria-label="Scroll to section: fork 检测静音"><span class="me-0.5">#</span>fork 检测静音</a></li></ul></li><li class><a class="block line-clamp-2 hover:text-accent mt-3" href="#配置-fork-更新流程" aria-label="Scroll to section: 配置 fork 更新流程"><span class="me-0.5">#</span>配置 fork 更新流程</a></li><li class><a class="block line-clamp-2 hover:text-accent mt-3" href="#新的开发流程" aria-label="Scroll to section: 新的开发流程"><span class="me-0.5">#</span>新的开发流程</a><ul><li class="ms-2"><a class="block line-clamp-2 hover:text-accent mt-2 text-[0.6875rem]" href="#1-设置本地项目-upstream-为官方仓库" aria-label="Scroll to section: 1. 设置本地项目 upstream 为官方仓库"><span class="me-0.5">#</span>1. 设置本地项目 upstream 为官方仓库</a></li><li class="ms-2"><a class="block line-clamp-2 hover:text-accent mt-2 text-[0.6875rem]" href="#2-将-upstream-的最新改动同步到-fork-仓库" aria-label="Scroll to section: 2. 将 upstream 的最新改动同步到 fork 仓库"><span class="me-0.5">#</span>2. 将 upstream 的最新改动同步到 fork 仓库</a></li></ul></li><li class><a class="block line-clamp-2 hover:text-accent mt-3" href="#3-修改代码并合并到-main-分支" aria-label="Scroll to section: 3. 修改代码并合并到 main 分支"><span class="me-0.5">#</span>3. 修改代码并合并到 main 分支</a></li><li class><a class="block line-clamp-2 hover:text-accent mt-3" href="#4-更新服务器的-hermes" aria-label="Scroll to section: 4. 更新服务器的 Hermes"><span class="me-0.5">#</span>4. 更新服务器的 Hermes</a></li><li class><a class="block line-clamp-2 hover:text-accent mt-3" href="#hermes-支持飞书-cardkit-卡片流式输出" aria-label="Scroll to section: Hermes 支持飞书 Cardkit 卡片流式输出"><span class="me-0.5">#</span>Hermes 支持飞书 Cardkit 卡片流式输出</a></li></ul></aside><article class="min-w-0 flex-1 break-words" data-pagefind-body><div id="blog-hero"><div class="aspect-h-9 aspect-w-16 mb-6"><img src="https://image.1874.run/blog/bc1fc4d4819a578c395c1c60f5c46262.png" alt="无需打散件补丁:用 fork 接管 Hermes 更新" width="1440" height="810" class="object-cover" loading="eager" fetchpriority="high"></div><h1 class="title mb-3 sm:mb-1">无需打散件补丁:用 fork 接管 Hermes 更新</h1><div class="flex flex-wrap items-center gap-x-3 gap-y-2"><p class="font-semibold"><time datetime="2026-06-27T08:00:00.000Z">2026年6月27日</time> / 5 min read</p><span class="rounded-lg bg-quote/10 p-1 text-quote">最后更新:<time datetime="2026-07-01T06:56:00.000Z" class="ms-1">2026年7月1日</time></span></div><div class="mt-3"><svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" class="me-1 inline-block h-6 w-6" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M7.859 6h-2.834a2.025 2.025 0 0 0 -2.025 2.025v2.834c0 .537 .213 1.052 .593 1.432l6.116 6.116a2.025 2.025 0 0 0 2.864 0l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-6.117 -6.116a2.025 2.025 0 0 0 -1.431 -.593z"></path><path d="M17.573 18.407l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-7.117 -7.116"></path><path d="M6 9h-.01"></path></svg><a class="cactus-link inline-block before:content-['#']" aria-label="View more blogs with the tag 赛博空间" href="/tags/赛博空间/" data-pagefind-filter="tag">赛博空间</a>, <a class="cactus-link inline-block before:content-['#']" aria-label="View more blogs with the tag hermes" href="/tags/hermes/" data-pagefind-filter="tag">hermes</a></div></div><div class="post-content prose prose-sm prose-cactus mt-12 prose-headings:font-semibold prose-headings:text-accent-2 prose-headings:before:absolute prose-headings:before:-ms-4 prose-headings:before:text-accent prose-headings:before:content-['#'] prose-th:before:content-none"><h2 id="前言">前言</h2>
47<p>我的 Hermes 是部署在局域网的机器上的,而目前 Hermes 不支持飞书渠道的 Cardkit 卡片消息,所以我自己打了补丁来实现。而在服务器上真实测试时,之前的流程是汇总改动的文件,然后去服务器上 Hermes 源代码目录中替换掉对应文件。但如果在服务器上使用<code>hermes update</code>更新时,又会被官方代码覆盖了(虽然可以恢复暂存,但不好应对冲突情况)。</p>
48<p>最近在 Claude 的帮助下,发现一个非常舒服的开发/更新流ç¨
48‹ã€‚</p>
49<h2 id="核心判断">核心判断</h2>
50<p>Hermes 的 <code>hermes update</code> 在拉代码阶段固定执行:</p>
51<div class="expressive-code"><link rel="stylesheet" href="/_astro/ec.qwcc5.css">
51<script type="module" src="/_astro/ec.0vx5m.js"></script>
51<figure class="frame is-terminal"><figcaption class="header"><span class="title"></span><span class="sr-only">Terminal window</span></figcaption><pre data-language="bash"><code><div class="ec-line"><div class="code"><span style="--0:#50FA7B;--1:#6F42C1">git</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">pull</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#BD93F9;--1:#005CC5">--ff-only</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">origin</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">&#x3C;branch></span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="git pull --ff-only origin <branch>"><div></div></button></div></figure></div>
52<p>所以更新来源由服务器部署目录里的 <code>origin</code> remote 决定。</p>
53<p>只要 <code>origin</code> 指向个人 fork,<code>hermes update</code> 就会从 fork 拉取 <code>main</code>,并继续执行 Hermes 自带的快照、pull、语法校验、回滚保护、清 bytecode、依赖重装、迁移等步骤。</p>
54<h3 id="fork-检测静音">fork 检测静音</h3>
55<p><code>hermes update</code> 检测到 <code>origin</code> 是 fork 时,可能会提示或尝试同步官方 upstream。为了让服务器更新只关注个人 fork,需要满足:</p>
56<ul>
57<li>服务器上没有 <code>upstream</code> remote。</li>
58<li>存在 <code>$HERMES_HOME/.skip_upstream_prompt</code>。</li>
59</ul>
60<blockquote>
61<p>注意:<code>.skip_upstream_prompt</code> 只负责静音 fork 检测提示,不负责改变代码拉取来源。真正让 update 拉 fork 的开关是 <code>origin</code>。</p>
62</blockquote>
63<h2 id="配置-fork-更新流程">配置 fork 更新流程</h2>
64<p>基于以上判断,可以设置新的更新流程。</p>
65<p>我的服务器的相关路径:</p>
66<ul>
67<li>Hermes 源码目录:<code>/usr/local/lib/hermes-agent</code></li>
68<li><code>HERMES_HOME</code>目录:<code>~/.hermes</code></li>
69</ul>
70<div class="expressive-code"><figure class="frame is-terminal"><figcaption class="header"><span class="title"></span><span class="sr-only">Terminal window</span></figcaption><pre data-language="bash"><code><div class="ec-line"><div class="code"><span style="--0:#8BE9FD;--1:#005CC5">cd</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">/usr/local/lib/hermes-agent</span></div></div><div class="ec-line"><div class="code">
71</div></div><div class="ec-line"><div class="code"><span style="--0:#96A1C2;--1:#616972"># 1. 改 origin 指向个人 fork</span></div></div><div class="ec-line"><div class="code"><span style="--0:#50FA7B;--1:#6F42C1">git</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">remote</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">set-url</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">origin</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">https://github.com/LetTTGACO/hermes-agent.git</span></div></div><div class="ec-line"><div class="code">
72</div></div><div class="ec-line"><div class="code"><span style="--0:#96A1C2;--1:#616972"># 2. 确认无 upstream remote(fork 检测静音前提)</span></div></div><div class="ec-line"><div class="code"><span style="--0:#50FA7B;--1:#6F42C1">git</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">remote</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">get-url</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">upstream</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#FF79C6;--1:#BF3441">2></span><span style="--0:#F1FA8C;--1:#032F62">/dev/null</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#FF79C6;--1:#BF3441">||</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#8BE9FD;--1:#005CC5">echo</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--1:#032F62"><span style="--0:#E9F284">"</span><span style="--0:#F1FA8C">无 upstream,OK</span><span style="--0:#E9F284">"</span></span></div></div><div class="ec-line"><div class="code">
73</div></div><div class="ec-line"><div class="code"><span style="--0:#96A1C2;--1:#616972"># 3. 建 skip 标记,有这个文件就行,不需要有内容</span></div></div><div class="ec-line"><div class="code"><span style="--0:#50FA7B;--1:#6F42C1">touch</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--1:#032F62"><span style="--0:#E9F284">"</span><span style="--0:#F1FA8C">~/.hermes/.skip_upstream_prompt</span><span style="--0:#E9F284">"</span></span></div></div><div class="ec-line"><div class="code">
74</div></div><div class="ec-line"><div class="code"><span style="--0:#96A1C2;--1:#616972"># 4. fetch fork 并对齐到 fork main(清掉工作区手工补丁)</span></div></div><div class="ec-line"><div class="code"><span style="--0:#50FA7B;--1:#6F42C1">git</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;
74--1:#032F62">fetch</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">origin</span></div></div><div class="ec-line"><div class="code"><span style="--0:#50FA7B;--1:#6F42C1">git</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">reset</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#BD93F9;--1:#005CC5">--hard</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">origin/main</span></div></div><div class="ec-line"><div class="code">
75</div></div><div class="ec-line"><div class="code"><span style="--0:#96A1C2;--1:#616972"># 5. 尝试一次Hermes更新,会自动重启</span></div></div><div class="ec-line"><div class="code"><span style="--0:#50FA7B;--1:#6F42C1">hermes</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">update</span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="cd /usr/local/lib/hermes-agent�git remote set-url origin https://github.com/LetTTGACO/hermes-agent.git�git remote get-url upstream 2>/dev/null || echo &#x22;无 upstream,OK&#x22;�touch &#x22;~/.hermes/.skip_upstream_prompt&#x22;�git fetch origin�git reset --hard origin/main�hermes update"><div></div></button></div></figure></div>
76<h2 id="新的开发流程">新的开发流程</h2>
77<h3 id="1-设置本地项目-upstream-为官方仓库">1. 设置本地项目 upstream 为官方仓库</h3>
78<p>如果需要 fork 仓库的代码能定期保持和官方仓库代码一致,可以设置此项:</p>
79<div class="expressive-code"><figure class="frame is-terminal"><figcaption class="header"><span class="title"></span><span class="sr-only">Terminal window</span></figcaption><pre data-language="bash"><code><div class="ec-line"><div class="code"><span style="--0:#50FA7B;--1:#6F42C1">git</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">remote</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">add</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">upstream</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">https://github.com/NousResearch/hermes-agent.git</span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="git remote add upstream https://github.com/NousResearch/hermes-agent.git"><div></div></button></div></figure></div>
80<h3 id="2-将-upstream-的最新改动同步到-fork-仓库">2. 将 upstream 的最新改动同步到 fork 仓库</h3>
81<div class="expressive-code"><figure class="frame is-terminal"><figcaption class="header"><span class="title"></span><span class="sr-only">Terminal window</span></figcaption><pre data-language="bash"><code><div class="ec-line"><div class="code"><span style="--0:#50FA7B;--1:#6F42C1">git</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">fetch</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">upstream</span></div></div><div class="ec-line"><div class="code"><span style="--0:#50FA7B;--1:#6F42C1">git</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">merge</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">upstream/main</span><span style="--0:#F8F8F2;--1:#24292E">     </span><span style="--0:#96A1C2;--1:#616972"># 冲突:解决后 git add + git commit</span></div></div><div class="ec-line"><div class="code"><span style="--0:#50FA7B;--1:#6F42C1">git</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">push</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">origin</span><span style="--0:#F8F8F2;--1:#24292E"> </span><span style="--0:#F1FA8C;--1:#032F62">main</span><span style="--0:#F8F8F2;--1:#24292E">        </span><span style="--0:#96A1C2;--1:#616972"># merge 不改写历史,普通 push 即可。</span></div></div></code></pre><div class="copy"><div aria-live="polite"></div><button title="Copy to clipboard" data-copied="Copied!" data-code="git fetch upstream�git merge upstream/main     # 冲突:解决后 git add + git commit�git push origin main        # merge 不改写历史,普通 push 即可。"><div></div></button></div></figure></div>
82<blockquote>
83<p>注意:<code>git merge</code> 会让提交记录多一条 merge 记录,如果要保持单线提交,就得用到 <code>git rebase upstream/main</code> 改写提交历史了。我暂时自用的话,就直接 merge了,不制造复杂度。</p>
84</blockquote>
85<h2 id="3-修改代码并合并到-main-分支">3. 修改代码并合并到 main 分支</h2>
86<p>不管是新建分支还是新建 worktree 进行开发,开发完只需要将提交合并到 fork ä
86»“库的 main 分支就行,然后推送到 fork 仓库。</p>
87<h2 id="4-更新服务器的-hermes">4. 更新服务器的 Hermes</h2>
88<p>直接执行<code>hermes update</code>,Hermes 的更新流程就变成从你的 fork 仓库 main 分支拉取最新代码了。</p>
89<h2 id="hermes-支持飞书-cardkit-卡片流式输出">Hermes 支持飞书 Cardkit 卡片流式输出</h2>
90<p>展示下我的成果。目前官方 Hermes 在飞书上的表现</p>
91<img src="https://image.1874.run/blog/3e8988c5ba1877f2bb15ea4c44d986e4.png" alt="image.png">
92<p>我打了补丁之后的效果</p>
93<img src="https://image.1874.run/blog/32eb5c8b82690954e4486670c75a33d5.png" alt="image.png">
94<p>因为目前我主要是自用,可能会有一些我没体验到的 BUG。如果有想用的话,可以直接按照【配置 fork 更新流程】设置为我的仓库就行。</p><!--<WebMentions />--><meta property="og:"><section id="comments" class="mt-16"></section>
94<script type="module">function e(e){let t=document.querySelector(`iframe.giscus-frame`);!t||!t.contentWindow||t.contentWindow.postMessage({giscus:e},`https://giscus.app`)}function t(){return document.firstElementChild&&document.firstElementChild.getAttribute(`data-theme`)}function n(){let e=document.querySelector(`#comments`),n=t()==`light`?`light`:`dark_dimmed`,r=document.createElement(`script`);r.src=`https://giscus.app/client.js`,r.setAttribute(`data-repo`,`LetTTGACO/blog.1874.cool`),r.setAttribute(`data-repo-id`,`R_kgDOLNI02w`),r.setAttribute(`data-category`,`General`),r.setAttribute(`data-category-id`,`DIC_kwDOLNI0284Cc6X-`),r.setAttribute(`data-mapping`,`og:title`),r.setAttribute(`data-strict`,`0`),r.setAttribute(`data-reactions-enabled`,`0`),r.setAttribute(`data-emit-metadata`,`0`),r.setAttribute(`data-input-position`,`bottom`),r.setAttribute(`data-theme`,n),r.setAttribute(`data-lang`,`zh-CN`),r.setAttribute(`data-loading`,`lazy`),r.setAttribute(`crossorigin`,`anonymous`),r.async=!0,e&&e.appendChild(r)}n(),document.querySelector(`#theme-btn`)?.addEventListener(`click`,()=>{e({setConfig:{theme:t()==`light`?`light`:`dark_dimmed`}})});</script>
94<div class="mb-10" aria-hidden="true"></div></div></article></div><button id="to-top-btn" class="z-90 fixed bottom-8 end-4 flex h-10 w-10 translate-y-28 items-center justify-center rounded-full border-2 border-transparent bg-zinc-200 text-3xl opacity-0 transition-all duration-300 hover:border-zinc-400 data-[show=true]:translate-y-0 data-[show=true]:opacity-100 dark:bg-zinc-700 sm:end-8 sm:h-12 sm:w-12" aria-label="Back to Top" data-show="false"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="h-6 w-6"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 15.75l7.5-7.5 7.5 7.5"></path></svg></button></main><footer class="site-footer mt-auto flex flex-col items-center justify-center gap-y-2 pb-4 pt-20 text-center align-top font-semibold text-gray-600 dark:text-gray-400 sm:flex-row sm:gap-x-20 sm:text-xs"><div>&copy; 1874&nbsp;2026.<span class="block">🚀&nbsp;<span><a href="https://www.notion.so" target="_blank" class="py-2 sm:py-0 sm:hover:text-textColor sm:hover:underline">Notion</a>&amp;</span><span><a href="https://elog.1874.cool" target="_blank" class="py-2 sm:py-0 sm:hover:text-textColor sm:hover:underline">Elog</a>&amp;</span><span><a href="https://astro.build" target="_blank" class="py-2 sm:py-0 sm:hover:text-textColor sm:hover:underline">Astro</a>&amp;</span><span><a href="https://vercel.com" target="_blank" class="py-2 sm:py-0 sm:hover:text-textColor sm:hover:underline">Vercel</a></span></span></div><nav aria-label="More on this site" class="flex flex-wrap items-center justify-center gap-y-2 text-sm sm:text-xs"><a href="/" class="mx-2 whitespace-nowrap py-1 sm:hover:text-textColor sm:hover:underline">首页</a><a href="/tags/vibecoding" class="mx-2 whitespace-nowrap py-1 sm:hover:text-textColor sm:hover:underline">VibeCoding</a><a href="/tags/赛博空间" class="mx-2 whitespace-nowrap py-1 sm:hover:text-textColor sm:hover:underline">赛博空间</a><a href="/tags/代码之外" class="mx-2 whitespace-nowrap py-1 sm:hover:text-textColor sm:hover:underline">代码之外</a><a href="/about" class="mx-2 whitespace-nowrap py-1 sm:hover:text-textColor sm:hover:underline">关于</a><a href="/links" class="mx-2 whitespace-nowrap py-1 sm:hover:text-textColor sm:hover:underline">友链</a></nav></footer></body></html>
94<script type="module" src="/_astro/BlogPost.astro_astro_type_script_index_0_lang.DVw77T0u.js"></script>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.