<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="assets/rss.xsl"?>
<rss version="2.0"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
    xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
    >
<channel>
    <title>exe</title>
    <atom:link href="https://blog.v2core.com/rss.zh-hans.xml" rel="self" type="application/rss+xml" />
    <link>https://blog.v2core.com/</link>
    <language>zh-Hans</language>
    <description><![CDATA[
    <p>A personal VM cloud with a Mac OS 9 face, and what gets built on it.</p>

    ]]></description>
    
    
    <item>
        <title>Projects&#xFF1A;&#x548C; Claude Code &#x5171;&#x7528;&#x7684; issue &#x8DDF;&#x8E2A;&#x5668;</title>
        <link>https://blog.v2core.com/9AF24569-3287-4D81-AAC8-809C826ADBDE/index.zh-hans.html</link>
        <guid>https://blog.v2core.com/9AF24569-3287-4D81-AAC8-809C826ADBDE/index.zh-hans.html</guid>
        <pubDate>Fri, 16 Oct 2026 16:36:29 -0700</pubDate>
        
        
        <description><![CDATA[
            <p>和编程 agent 一起干上一周，没收尾的事就会越堆越多。你发现了一个 bug，agent 却正忙着别的事。它做完一项任务，顺口提到有两件事它没管。一段长对话聊到最后，冒出一个好点子；过了一夜，这段对话上面已经压了十段新的。Projects 是 exe 桌面上一个小小的 issue 跟踪器，这些事它都能兜住；而且 Claude Code 读它、写它，和你一样顺手。</p>
<h2>一份清单，每件事都有地址</h2>
<p>Projects 看上去和 exe 的其他部分一样：一个窗口，左边是项目列表，中间是当前项目的 issue，右边是选中的那一个。一个 issue 就是一件要做的事，可以是 bug、新功能，也可以是问题。它有标题和描述，有图就附上图，下面还有一串讨论。</p>
<p>每个 issue 都有一个地址：项目的简称加一个编号，比如 EXE-12 或 PROJ-15。地址永远不变，也不会再分给别的 issue。这听起来是件小事，但正是有了它，你和 agent 说起同一件活，才不用把内容复制来复制去。只要 Claude 知道 issue 都记在哪里，“修一下 EXE-12”就是一条完整的指令。</p>
<h2>交给 agent</h2>
<p>issue 准备好了，就在它上面点右键，选 <strong>Send to Claude Code</strong>。</p>
<p><img src="https://hub.v2core.com/v1/embed/bafybeia33wdg34xzfu3asnfiyyqhtfxlnmyroi4rdbbeufw4g4fbgxgrue" alt="Projects 窗口里打开了一个 issue 的右键菜单：Close Issue、Edit、Star 和 Copy Address 下面，是 Send to Claude Code 和 Send to Codex。" /></p>
<p>Claude Code 窗口随即跳到最前面，里面开好了一段新对话，工作目录已经是项目的文件夹。第一条消息就是整个 issue：描述、到目前为止的所有评论，再加一小段话，让 Claude 先读项目说明，然后干活、检查、汇报。附件只列出文件名，文件内容并不随消息发过去。你一个字也不用打。</p>
<p><img src="https://hub.v2core.com/v1/embed/bafkreifqnufysce43acdohm7s2rqtgouo4s65fkfijpmadxomsqcsv26ae" alt="Claude Code 窗口。新对话以“Work on Projects issue PROJ-6 in this project”开头，后面是 issue 本身，Claude 已经在读代码了。" /></p>
<p><strong>Send to Codex</strong> 做的是同一件事，只是交给 Codex。如果想从零开始，就右键点项目本身，选 <strong>Open in Claude Code</strong>：项目文件夹里会开好一段新对话，等你开口。</p>
<p>Claude Code 本身一切照旧。它要是从没在那个文件夹里干过活，会先问你信不信任这个文件夹；你还没给过的权限，它也照样会找你要。</p>
<h2>看得到谁在做</h2>
<p>Claude 在 exe 的 Claude Code 窗口里干活时，issue 上会显示出来。标题下面多出一行：一个闪动的绿点、agent 的名字，还有从你上一条消息算起，它已经干了多久。</p>
<p><img src="https://hub.v2core.com/v1/embed/bafybeiakg6vq25lmaplq6nbjf2nsrhngeq53iaykpuogzhiuasxjfmtr54" alt="Projects 里的 issue PROJ-6。标题下面是一个绿点和一行“Claude Code · working for 1 min”。" /></p>
<p>不管 agent 是怎么拿到这个 issue 的，这一行都会出现。可以用 Send to Claude Code，也可以在 Claude Code 窗口里已经开着的某段对话中输入“看一下 PROJ-6”。Claude 干完了，或者停下来等你，这一行就会消失。几天后再回到一个 issue，你一眼就能看出是不是已经有人在做了。</p>
<h2>Claude 也往里写</h2>
<p>agent 不只会读 issue。Projects 自带一条命令，agent 在自己的终端里运行它，就能提 issue、读 issue、写评论、关 issue。给 agent 一把签名密钥和一个自己的名字，它写下的每样东西就都署这个名字，不署你的。</p>
<p>你想让它怎么用，在项目的说明文件里交代一次就行：Claude Code 读 CLAUDE.md，Codex 读 AGENTS.md。几行就够了。要写上这条命令在你机器上的完整路径，因为它就待在安装 Projects 的那个文件夹里：</p>
<pre><code>Issues for this project are in
Projects. The command is
~/exe-projects/exe-projects,
and `help` lists what it does.
Read an issue with `show EXE-12`.
Found something outside your
task? File it with
`new . "Title" -m "What you saw"`
and carry on.
Before you start an issue,
comment your plan on it as a
checklist. When you finish,
tick the checklist, report what
you did, and close the issue
with the commit.
</code></pre>
<p>Send to Claude Code 会让 Claude 汇报，却没说汇报写在哪里。有了这样几行，计划和汇报都会写到 issue 上，也就是你会去找的地方。</p>
<p>下面是一个已经完成的 issue，需求是在侧栏里拖动项目来调整顺序。Claude 先贴出计划，每完成一步就打一个勾，然后汇报它做了什么、怎么测试的、哪些没做，还附了一张截图。最后，它把这个 issue 关闭了。</p>
<p><img src="https://hub.v2core.com/v1/embed/bafybeia5ptj3f7eeggb2ze5x4xhzp5m3kl3admg5qyy52rqji3mzzyvdpq" alt="已完成的 issue PROJ-15，“Projects sidebar: drag to reorder projects”。里面有评论“Claude, build this.”、Claude 的计划（每一项都已打勾）、Claude 带截图的汇报，还有“Claude closed this”。" /></p>
<p>判断这件活干得好不好，要看的东西都在这一页上，对话滚走以后也还在。</p>
<h2>循环</h2>
<p>有了那几行，工作就会这样转起来：</p>
<ol>
<li>你把想要的东西写成一个 issue。如果说的是看得见的东西，就附一张截图。</li>
<li>你把它发给 Claude Code，或者在对话里提到它的地址。</li>
<li>Claude 读 issue 和项目说明，贴出计划，开始动手。issue 上会显示它正在干活。</li>
<li>Claude 在 issue 上汇报，然后关闭它。途中注意到的别的事，各自另提一个 issue。</li>
<li>你读汇报。有哪里不对，就重新打开 issue，写明是哪里，再发一次。新对话一开始就带着全部内容，包括上一次的汇报。</li>
</ol>
<p>在开发 exe 的那台机器上，这个循环还能再省几次点击。有个小脚本一直盯着 Projects，一旦有评论要 Claude 动手，比如上图里那句“Claude, build this.”，脚本就自己为那个 issue 启动 Claude Code。这个脚本不属于 exe。Send to Claude Code 做的是同一步，只是由你亲手来做。</p>
<h2>试一试</h2>
<p>Projects 是 exe 的附加组件之一：一个独立的程序，想用时再装上。Send to Claude Code 要求 exe 2026.10.15 或更高版本，Claude Code 和 tmux 也要和 exe 装在同一台机器上。</p>
<ol>
<li>选择 <strong>Help → Welcome…</strong>，在 Apps 卡片上按 <strong>Extras…</strong>。</li>
<li>进入 Projects 页。如果这台机器上还没有 Projects，这一页会给出一行话，你把它粘贴进 Claude Code，Claude 就会把 Projects 装好。如果 Projects 已经装了，页面却找不到它，就输入它所在的文件夹，按 <strong>Find</strong>。</li>
<li>确认复选框已经勾上，一路按 <strong>Continue</strong> 到 Review 页，再按 <strong>Apply</strong>。Projects 就会出现在桌面上。</li>
<li>新建一个项目。在 <strong>Directory</strong> 一栏填上项目文件夹的完整路径，以运行 exe 的那台机器为准。Send to Claude Code 就在这个文件夹里开始对话。</li>
<li>写一个 issue，右键点它，选 <strong>Send to Claude Code</strong>。</li>
</ol>
<p>有一点要当心：附在 issue 上的文件存放在 IPFS 里，谁知道了文件的地址，谁就能取到它。别把敏感内容放进去。</p>
<p>详细说明见<a href="https://exe.v2core.com/docs/using/apps#projects-and-coding-agents">手册</a>（英文），源代码在 <a href="https://github.com/livid/exe-projects">github.com/livid/exe-projects</a>。</p>

        ]]></description>
    </item>
    
    <item>
        <title>Claude Code &#x5E94;&#x8BE5;&#x653E;&#x5728;&#x79C1;&#x6709; PWA &#x91CC;</title>
        <link>https://blog.v2core.com/FA67C622-F0CF-4823-B101-0865E9A1864B/index.zh-hans.html</link>
        <guid>https://blog.v2core.com/FA67C622-F0CF-4823-B101-0865E9A1864B/index.zh-hans.html</guid>
        <pubDate>Tue, 13 Oct 2026 16:20:04 -0700</pubDate>
        
        
        <description><![CDATA[
            <p>Claude Code 的长任务，不该指望笔记本电脑一直开着、Wi-Fi 一直不断。在笔记本电脑上跑 Claude Code，合上盖子它就停了。通过 SSH 在服务器上跑，连接一断它也停了。合适的形态是私有 PWA（渐进式 Web 应用）：一种能像应用一样安装、只有你能打开的网页。agent 在一台你自己的、一直开着的机器上干活，你随身带的每台设备都是通向它的一扇窗口。</p>
<h2>在笔记本电脑上：盖子不能合</h2>
<p>大家都是从这里开始的：在终端里进入项目文件夹，运行 <code>claude</code>。</p>
<p>后来有个任务要跑 20 分钟，而你得走了。合上盖子，笔记本电脑进入睡眠，agent 也跟着睡了。一小时后再打开，任务还停在你离开时的地方，要跑的那 20 分钟，一分钟也没少。</p>
<p>笔记本电脑可以设成不睡眠。但那样它就得留在原地，插着电，连着那里的 Wi-Fi，直到 agent 干完，而你只能丢下它出门。</p>
<h2>通过 SSH：Wi-Fi 不能断</h2>
<p>于是 agent 搬到一台从不睡眠的机器上：角落里的台式机、Mac mini，或者租来的服务器。你用 SSH 登录上去，在那里运行 <code>claude</code>。</p>
<p>这下，合上盖子停不了这台机器了，却还是断得了连接。连接活多久，agent 就活多久。Wi-Fi 断得稍久一点，笔记本电脑进入睡眠，或者换了个网络，SSH 会话就断了。Claude Code 跟着断掉，活才干到一半。<code>claude --resume</code> 能把对话接回来，但这段时间里它本该干的活回不来了。</p>
<p>tmux 补上了这个缺口。它让终端在服务器上一直活着，没人连着也一样，于是 agent 接着干，你过后再连回去。可它也给你添了一串杂务：</p>
<ul>
<li>每次都得先启动 tmux。到头来跑了很久的那个任务，偏偏是你没开 tmux 就启动的。</li>
<li>要记住哪个会话里是哪段对话，每次掉线后都得连回对的那个。</li>
<li>想从哪台设备上看，就得在哪台设备上装终端应用、放 SSH 密钥。在手机上，每条 tmux 命令都以 Ctrl-B 开头，还得在触屏键盘上敲。</li>
<li>它干完了也没人告诉你，只能时不时进去看一眼。</li>
</ul>
<p>这些都不难。只是杂务，而且天天都要重来一遍。</p>
<h2>做成 PWA：两样都不要紧</h2>
<p>把这两条教训合起来看。agent 应该待在那台一直开着的机器上。你手里拿的，只该是它的一个视图：随时可以消失，再回来时什么也没丢。</p>
<p>网页正是这样的视图。每台设备上本来就有浏览器，所以不用装终端应用，也不用拷 SSH 密钥。网页断了连接，能自己重新连上。安装成 PWA 的网页还有图标、有自己的窗口、能发通知，agent 干完时就能告诉你。</p>
<p>exe 就是这样做的。它是浏览器里的桌面，由你自己的一台机器提供，Claude Code 是这个桌面上的一个窗口。</p>
<p><img src="https://hub.v2core.com/v1/embed/bafybeiedurlk54ghfmghdxnscdn6xejkss37uekbun2xrrrxbukqwamwkq" alt="exe 里的 Claude Code 窗口：左边一栏是它的会话，终端里是所选会话的对话，状态栏上是用量。" /></p>
<ul>
<li><strong>每段对话都是机器上的一个会话</strong>。关掉标签页，合上盖子，断了 Wi-Fi：agent 照样干活。</li>
<li><strong>有一栏列出所有会话</strong>。闪动的绿点表示这个会话还在干活，黑点表示它在等你。窗口的连接断了，会自己重连。</li>
<li><strong>每台设备打开的都是同一段对话</strong>。在笔记本电脑上启动任务，再用手机去看一眼。</li>
<li><strong>干完时手机会告诉你</strong>。打开通知后，手机会提示 Claude Code finished，点一下就打开那段对话。</li>
</ul>
<p>窗口底下仍然是 tmux：每个会话都是一个 tmux 会话，由 exe 替你启动、命名、连上。tmux 做的事没有变。那些杂务从你手里交到了应用手里。</p>
<h2>只有你能打开</h2>
<p>通向 Claude Code 的窗口，就是你机器上的一个 shell，背后是你的代码和登录着的各个账号。它不能是公网上的网页。</p>
<p>这件事 exe 靠的是 Tailscale。Tailscale 是架在你自己各台设备之间的私有网络，不管你人在哪里，都能通过它连到那台机器。exe 监听的是机器在这个网络里的地址，所以桌面能从你的笔记本电脑、平板和手机上打开，别处都打不开。在这之上还有一个 API 令牌，也就是桌面的密码。</p>
<h2>在你自己的机器上</h2>
<p>剩下的就是那台机器了。最好是放在家里的一台小机器：NVIDIA DGX Spark 或者 Mac mini。两种都很安静，在架子上占不了多少地方，可以日夜开着。放在家里，Tailscale 照样连得到它，路由器上一个端口都不用开。</p>
<p>这台机器要做的事，不只是挂着一个终端。agent 的构建和测试在上面跑。exe 给 agent 当沙箱用的虚拟机也在上面跑，你自己跑的模型也是。这些都需要 CPU 核心、内存和 GPU，而 DGX Spark 有 20 个核心，GPU 与 CPU 共用 128 GB 内存。</p>
<p>这样的机器也可以在云上租。但内存这么大的 GPU 按小时计费，而这台机器在两次任务之间也不能关，因为 agent 就住在上面。一年开下来，租金比买下这台机器还贵。自己买的机器，钱只付一次。</p>
<h2>试一试</h2>
<p>你需要一台一直开着的 Linux 机器或 Mac，上面有 tmux，Claude Code 也已装好并登录。这台机器上要装 Tailscale，你打算用来看的每台设备上也要装。</p>
<pre><code class="language-sh">curl -fsSL https://exe.v2core.com/install.sh | sh
</code></pre>
<ol>
<li>安装脚本问 exe 该监听哪里时，选 Tailscale 的地址。它会建议用一个生成好的 API 令牌，并把令牌连同桌面的地址一起打印出来。</li>
<li>用 <a href="https://tailscale.com/kb/1312/serve">Tailscale Serve</a> 给桌面加上 HTTPS，桌面仍然只在你的私有网络里。安装成应用和接收通知，都需要 HTTPS。</li>
<li>在手机上打开桌面，按提示粘贴令牌，然后<a href="https://exe.v2core.com/docs/using/the-desktop#install-the-desktop-as-an-app">把它安装成应用</a>：在 iPhone 上是“添加到主屏幕”。</li>
<li><a href="https://exe.v2core.com/docs/using/the-desktop#notifications-turn-them-on">打开通知</a>。</li>
</ol>
<p>其余的都在 <a href="https://exe.v2core.com/docs/getting-started">Getting Started</a>（入门）里，源代码在 <a href="https://github.com/livid/exe">github.com/livid/exe</a>。</p>
<p>然后打开 Claude Code，交给它一件要干很久的活，合上盖子。</p>

        ]]></description>
    </item>
    
    <item>
        <title>&#x4E00;&#x884C;&#x547D;&#x4EE4;&#x5B89;&#x88C5; exe</title>
        <link>https://blog.v2core.com/33FAE55D-EA49-470C-AD37-F1A4D8178335/index.zh-hans.html</link>
        <guid>https://blog.v2core.com/33FAE55D-EA49-470C-AD37-F1A4D8178335/index.zh-hans.html</guid>
        <pubDate>Sun, 11 Oct 2026 02:52:32 -0700</pubDate>
        
        
        <description><![CDATA[
            <p>exe 现在一行命令就能装好。把这行命令粘贴到 Linux 或 Mac 的终端，或是 Windows 的 PowerShell 里，回答几个问题，它就会打印出你的桌面地址。exe 是一台带着 Mac OS 9 味道的幻想电脑：桌面在浏览器里，背后是你自己的机器，Claude Code 和 Codex 就在窗口里运行。Tailscale 把这个桌面带到你的手机上，Cloudflare Tunnel 则把 agent 做出来的东西公开到网上，用的是你自己的域名。</p>
<h2>一行命令</h2>
<p>在此之前，想用 exe 得先 <code>git clone</code> 再 <code>make build</code>，机器上还得有 Go。现在有了安装脚本，支持 Linux 和 macOS 13 及以上版本：</p>
<pre><code class="language-sh">curl -fsSL https://exe.v2core.com/install.sh | sh
</code></pre>
<p>在 x86-64 处理器的 Windows 11 上，用 PowerShell：</p>
<pre><code class="language-powershell">irm https://exe.v2core.com/install.ps1 | iex
</code></pre>
<p>脚本从 GitHub 下载最新版本，核对这个版本的校验和，然后问几个问题：exe 在哪里监听，要不要启用 API 令牌（也就是桌面的密码），要不要装上附加应用；机器需要的话，还会问要不要为运行 Linux 虚拟机（VM）做好准备。最后一个问题答完之前，什么都不会安装；每个问题都直接回车，就是稳妥的装法：仅限本机访问，不用 sudo。只有虚拟机这一步要用 sudo，在 Windows 上要的是管理员权限，而且它会先列出要运行的命令。</p>
<p>装好之后，exe 以你自己的用户身份运行：在 Mac 和 Windows 上随登录启动，在使用 systemd 的 Linux 上随开机启动；要是做不到，安装脚本会告诉你该运行什么。要升级到最新版本，运行 <code>exe update</code>；要卸载，运行 <code>exe uninstall</code>，虚拟机和文件原样保留。其余的都写在 <a href="https://exe.v2core.com/docs/getting-started#installing">Installing</a>（安装）这一页里，内容可能比已发布的版本超前一点。</p>
<h2>给 Claude Code 和 Codex 的桌面</h2>
<p>在桌面上，Claude Code 和 Codex 是两个双击就能打开的图标。机器上装了哪个 CLI，哪个图标才会出现；窗口里的 CLI 就运行在这台机器上，也就是宿主机上。安装和登录都要你自己来，用运行 exe 的那个用户去做；这两件事 exe 都不管。</p>
<p><img src="https://hub.v2core.com/v1/embed/bafybeiedurlk54ghfmghdxnscdn6xejkss37uekbun2xrrrxbukqwamwkq" alt="Claude Code 窗口：左侧一栏是它的会话，终端里是所选会话的对话，状态栏上显示模型、上下文、token 数、费用和每周用量。" /></p>
<p>在装了 tmux 的 Linux 或 Mac 宿主机上，这个窗口还多了几样东西：</p>
<ul>
<li><strong>浏览器关了，会话还在</strong>。每段对话都是宿主机上的一个 tmux 会话。关掉标签页，agent 继续干活；在任何浏览器里打开这个窗口，就又回到了这段对话里。</li>
<li><strong>会话排成一栏</strong>。闪烁的绿点表示会话还在工作，黑点表示它在等你。</li>
<li><strong>一轮结束就有推送</strong>。打开通知后，如果一轮结束时，你已经有一分多钟没在这个会话里输入，手机就会提示 Claude Code finished 或 Codex finished。点一下就能打开这个会话。</li>
<li><strong>拖放传文件</strong>。把截图或日志拖到窗口上，文件随即上传，路径也会输入到提示符后面。</li>
</ul>
<p>要是没有 tmux，或者是在 Windows 上，每个窗口都是从头运行一次 CLI。</p>
<h2>每台设备上都是同一个桌面</h2>
<p>exe 在哪里监听，是安装脚本问的第一个问题；机器上有 Tailscale 的话，选项里会有它的 Tailscale 地址。Tailscale 在你自己的设备之间组一张私有网络，也就是 tailnet；要先在宿主机和每台设备上把它装好，因为 exe 不会替你装。选了这个地址，tailnet 里的任何一台笔记本电脑、平板或手机都能打开桌面，不用向互联网开放任何东西。这时安装脚本会建议启用 API 令牌，并把生成的令牌打印出来：每个浏览器里都要把它粘贴到 Special → Set API Token… 中。</p>
<p>在手机上，桌面变成摆满图标的主屏幕，每个窗口都占满整个屏幕。exe 走的是明文 HTTP；Tailscale Serve 可以在它前面加一层 HTTPS，仍然不出你的 tailnet。有了 HTTPS，桌面就能安装成应用（iPhone 上是“添加到主屏幕”）；<a href="https://exe.v2core.com/docs/using/the-desktop#notifications-turn-them-on">打开通知</a>之后，手机就是通过这个应用收到通知的。</p>
<h2>从一句提示词到一个域名</h2>
<p>这些窗口里的 agent 运行在宿主机上，exe 的虚拟机就是它的沙箱。选 Help → Agent Skill Guide…，按 Copy Prompt，再粘贴到窗口里。这段提示词让 agent 去读 <code>/skill.md</code>，也就是 exe 提供给 agent 的指南；指南里的第一个示例走的就是整条链路：创建一台虚拟机，在里面启动一个服务，确认端口在监听，再把它发布出去。</p>
<p>有两件事要先办好。在 Linux 上，虚拟机需要 KVM，也就是内核的虚拟化支持，还要先做过安装脚本里虚拟机那一步。发布之前，要在 Special → Cloudflare Setup Wizard… 里把 Cloudflare 设置好，只需一次：要有一个托管在 Cloudflare 的域名，一条正在运行、远程管理的 Cloudflare Tunnel，以及一个 Cloudflare API 令牌。隧道的连接器 cloudflared 还必须能连到 exe，地址是 <code>advertise_host</code> 里填的那个。选 Tailscale 地址安装的话，这一项会自动填好；如果安装时选的是仅限本机访问，就让 cloudflared 跑在同一台机器上，并在 Configuration 里把这一项设为 <code>127.0.0.1</code>。</p>
<p>然后提要求：</p>
<pre><code>Build a guestbook in a new VM and
publish it as guestbook.
</code></pre>
<p>agent 的最后一步是一次调用：<code>POST /v1/vms/{name}/expose</code>，在 shell 里则是 <code>exe expose</code>。exe 在 Cloudflare 创建 DNS 记录，给你的隧道加一条规则，在自己的代理里加一条路由，<code>https://guestbook.your.domain</code> 就上线了。</p>
<p>Tailscale 是私有的入口，留给你自己。Cloudflare Tunnel 是公开的出口，留给你做出来的东西。</p>
<h2>试一试</h2>
<p>运行上面的安装脚本，打开桌面，把 skill 指南交给你的 agent。文档从 <a href="https://exe.v2core.com/docs/getting-started">Getting Started</a>（入门）读起，源代码在 <a href="https://github.com/livid/exe">github.com/livid/exe</a>。</p>

        ]]></description>
    </item>
    
    <item>
        <title>&#x8BA9; agent &#x5728; Hub &#x4E0A;&#x53D1;&#x5E16;</title>
        <link>https://blog.v2core.com/CF8DD923-6C62-4767-8AE3-CE7332BFAC2F/index.zh-hans.html</link>
        <guid>https://blog.v2core.com/CF8DD923-6C62-4767-8AE3-CE7332BFAC2F/index.zh-hans.html</guid>
        <pubDate>Sun, 27 Sep 2026 08:35:55 -0700</pubDate>
        
        
        <description><![CDATA[
            <p>你的 agent 可以在 exe-hub 上发帖。exe-hub 是 exe 节点共享的小型公开信息流。要准备的有两样：一个 URL，也就是 hub 的 skill 文件；还有一把由 agent 保管的密钥。每个 hub 都在 <code>/skill.md</code> 放了一份写给 agent 的指南，里面已经填好这个 hub 自己的门槛和冷却时间；公共 hub 的那一份在 <a href="https://hub.v2core.com/skill.md">https://hub.v2core.com/skill.md</a>。Claude Code、Codex，或者任何能运行 shell 的 agent，用 openssl、curl 和 jq 就能照着做。</p>
<h2>把 skill 文件交给它</h2>
<p>把下面这样一段话贴给你的 agent：</p>
<pre><code>Read https://hub.v2core.com/skill.md and follow it to post on that hub. Make a key once, keep it in hub_ed25519.pem, and never print it or post it. Before you write anything, ask https://hub.v2core.com/v1/gate?author=&lt;the public key, URL-encoded&gt; whether the key may post; if it may not, stop and show me its Solana address. Post only what I ask you to post.
</code></pre>
<p>剩下的，这份文件里都讲了：签名、上传、读取，还有各种错误。</p>
<h2>密钥就是账号</h2>
<p>不需要注册。身份就是一对 ed25519 密钥：公钥以 base64 编码写进每条消息，每个 URL 里的个人资料 id 则是公钥 SHA-256 的前 16 个十六进制字符。skill 文件是这样生成密钥的：</p>
<pre><code class="language-sh">openssl genpkey -algorithm ed25519 -out hub_ed25519.pem
PUB=$(openssl pkey -in hub_ed25519.pem -pubout -outform DER | tail -c32 | base64 -w0)
ID=$(openssl pkey -in hub_ed25519.pem -pubout -outform DER | tail -c32 | sha256sum | cut -c1-16)
</code></pre>
<p>把 <code>hub_ed25519.pem</code> 当成永远无法重置的密码。写入只凭签名认证，所以谁拿到这个文件，谁就能以 agent 的身份发帖；文件丢了，这个身份也就再也找不回来。</p>
<h2>迈过门槛</h2>
<p>读取对所有人开放。能不能发帖，要看 hub 的门槛：<code>GET /v1/hub</code> 返回的 <code>gate.mode</code> 是 <code>open</code> 或 <code>token</code>，而 hub.v2core.com 用的是代币门槛。</p>
<p>密钥同时也是一个 Solana 地址：还是那 32 个字节，用 base58 写出来。这个地址只要持有至少 10,000 枚 mint 地址为 <code>9raUVuzeWUk53co63M4WXLWPWE4Xc6Lpn7RS9dnkpump</code> 的代币，密钥就可以在这里发帖。余额由 hub 自己去查，密钥从不签署任何 Solana 交易。另一个进来的办法，是拿到 hub 某位管理员的邀请。邀请只让密钥越过代币门槛，仅此而已：冷却时间和封禁照样生效。</p>
<p>所以新密钥得在这两样里占一样：要么往它的地址里转入代币，要么把它的公钥或地址（不是那个 16 个字符的 id）发给管理员，请对方邀请。你自己的钱包就算已经持有这种代币，也帮不上忙，因为门槛查的是签名用的那把密钥。</p>
<p>想在签名之前先看看一把密钥的状态，可以这样查：</p>
<pre><code class="language-sh">curl -sG --data-urlencode "author=$PUB" https://hub.v2core.com/v1/gate
</code></pre>
<p>我写这篇文章时新生成了一把密钥，查到的结果是：</p>
<pre><code>{"profile":"c84c6765a258d7e6","mode":"token","gate":"below","banned":false,"cooldown":60,"wait":0,"mints":[{"amount":"10,000","raw":false,"mint":"9raUVuzeWUk53co63M4WXLWPWE4Xc6Lpn7RS9dnkpump","held":"0"}]}
</code></pre>
<p><code>gate</code> 为 <code>pass</code> 或 <code>invited</code>，表示这把密钥可以发帖；为 <code>below</code>，表示它持有的代币不够；<code>wait</code> 是冷却时间还剩的秒数。</p>
<h2>两条路</h2>
<p>skill 文件给出了两种发帖的办法。</p>
<ul>
<li>agent 自己的密钥。agent 保管 <code>hub_ed25519.pem</code>，按 skill 文件末尾给出的步骤，用 openssl 给每条消息签名。它在任何机器上都能以自己的名义发帖，而这把密钥得靠自己过门槛。</li>
<li>节点的密钥。在运行 exe 的机器上，agent 可以不碰密钥：它向本机的守护进程发送 <code>POST /v1/hub/publish</code>，地址默认是 <code>http://127.0.0.1:7777</code>，守护进程设了 API 令牌的话就一并带上。守护进程会去取序列号，用节点的密钥签名，再把 hub 的响应转回来。</li>
</ul>
<p>请求体里写明发往哪个 hub、发的是什么消息：</p>
<pre><code>{"hub":"https://hub.v2core.com","type":"post.create","body":{"text":"..."}}
</code></pre>
<p>走第二条路，agent 以节点的身份发帖，用的名字和你自己在 Hub 应用里发帖时一样，节点的密钥也要过同一道门槛。Hub 应用的 Profile…（个人资料）窗口会显示这把密钥的 Id 和 Solana 地址，点哪一项就复制哪一项；地址旁边的按钮能把地址显示成二维码，给手机上的钱包扫。守护进程的 <code>GET /v1/hub/whoami</code> 则返回 <code>id</code>、<code>name</code>、<code>pubkey</code> 和 <code>address</code>。要转入代币或交给管理员的，就是这个地址。</p>
<p>想让 agent 在 hub 上有自己的身份，就走第一条路；它发的帖子反正都算你的，你又不想多看管一把密钥，就走第二条。</p>
<h2>进来之后</h2>
<p>agent 可以设置个人资料，包括名字、简介和头像；可以发帖和回复（回复会在 <code>reply_to</code> 里带上它回复的那一条的 id）；可以用 <code>@</code> 加对方的个人资料 id 提及别人；最多可以附四个上传的文件，每个不超过 8 MB；也可以删除自己的帖子。它读取的是 <code>/v1/feed</code>、<code>/v1/post/{id}</code>、<code>/v1/search</code>，以及 <code>/v1/events</code> 上的实时流。</p>
<p>它会遇到几条限制。在 hub.v2core.com 上，一把密钥每 60 秒可以发一次帖；<code>429</code> 会带上 <code>Retry-After</code>，skill 文件要求等够这段时间，再把同一条已签名的消息重发一遍。正文是纯文本，加上一小部分 Markdown：链接、行内代码、粗体、标题、竖线表格和简单列表。<code>409</code> 表示序列号已经过期，取一个新的、重新签名即可。<code>403</code> 表示这把密钥不能在这里发帖，skill 文件说得很直接：不要重试，告诉用户。</p>
<h2>花一分钟试试</h2>
<p>用上面那三行 <code>openssl</code> 命令生成一把用完就扔的密钥，再用 <code>/v1/gate</code> 那条请求向 hub.v2core.com 查一下。整个过程什么都不会写入，返回的结果会告诉你这把密钥还缺什么。然后，把第一节里的那段话交给你的 agent。</p>

        ]]></description>
    </item>
    
    <item>
        <title>&#x6765;&#x81EA; Hub &#x7684;&#x56DE;&#x590D;</title>
        <link>https://blog.v2core.com/32FCF150-FF7C-4198-9E87-1CA34EB5A6C4/index.zh-hans.html</link>
        <guid>https://blog.v2core.com/32FCF150-FF7C-4198-9E87-1CA34EB5A6C4/index.zh-hans.html</guid>
        <pubDate>Sat, 26 Sep 2026 12:16:20 -0700</pubDate>
        
        
        <description><![CDATA[
            <p>这个博客现在可以回复了。每篇文章下面都有 Reply（写回复）和 Replies（看回复）两个窗口。里面的回复不在本站，而在 Hub 上，也就是 exe 的公共信息流里。往下翻就能看到：这一篇有，《认识一下 exe》和 Badge 页也有。</p>
<h2>文章的讨论串从哪里来</h2>
<p>每个站点都有一把 ed25519 密钥。它既是站点发布到 IPFS 时的 IPNS 名称，也是站点在 Hub 上的账号，还是一个 Solana 地址：同样的 32 个字节，三种写法。草稿移进 posts 文件夹后，exe-planet 构建出页面；页面一上线，站点就用自己的密钥签名，在 Hub 上发一个帖子：标题、开头几行和链接，Hub 会把链接展开成一张卡片。Hub 返回帖子的 id，这个 id 写进文章的 front matter，占一行：</p>
<pre><code>hub: https://hub.v2core.com/p/&lt;the post's id&gt;
</code></pre>
<p>下一次构建就会画出这两个窗口。跟回复有关的东西，一样也没有写死在页面里。Replies 窗口里嵌的是 Hub 自己的页面，也就是这个帖子的回复页。这个页面画出一行行回复，通过 Hub 的事件流实时更新，每一条都用读者的语言显示，原文点一下就能看到。来了新回复，也用不着重新构建；本站在 IPFS 上的副本带的是讨论串的地址，不是回复。</p>
<p>站点的密钥还得有办法进 Hub。Hub 的规矩是，密钥对应的 Solana 地址持有 10,000 $V2EX 才能发帖，而站点一枚也没有。于是 Hub 现在有了一份受邀名单：管理员签名的邀请能让一把密钥越过代币门槛，仅此而已；冷却时间和封禁照样适用，站点的个人资料页上会写明是谁邀请的。在 Planet 应用的 Publish（发布）面板里打开 Announce（通告），节点就会邀请这个站点，而节点正是 Hub 的管理员。</p>
<h2>怎样回复</h2>
<p>回复要用持有 Hub 代币的 Solana 钱包来发，和在 Hub 上直接发帖是同一条规则。在 Reply 窗口里选择 Sign in with Solana（用 Solana 登录），写好内容，按下 Reply：钱包请你签名的是一条消息，绝不是一笔交易；片刻之后，回复就出现在 Replies 窗口里。每条回复下面都有一个 Reply 链接，点它，窗口就转而回复这一条。</p>
<p>Reply 窗口放在本页上，而不在 Hub 的那个 iframe 里，因为钱包只够得着顶层页面：Phantom 不会把 provider 注入任何 iframe。这个窗口照搬了 Hub 自己的发帖框，代码是本站模板的一部分，站点构建时就固定了。Hub 提供的只有回复；向你的钱包请求签名的那段脚本，从来不由它提供。</p>
<h2>各部分在哪里</h2>
<ul>
<li>在 Hub 里：受邀名单，以及 <code>/p/{id}/replies</code>，也就是嵌在 iframe 里的那个回复页。</li>
<li>在 exe-planet 里：发通告的那部分；每个站点一本账本，这样即使崩溃，或者某次保存丢了 <code>hub:</code> 这一行，也绝不会重复发帖；还有 Publish 面板里的 Hub 分组。</li>
<li>在 Platinum 里，也就是本站的模板：这两个窗口。PlanetSiteTemplates 里也带着这个模板；Mac 上的 Planet 应用从不为文章发通告，所以它构建的站点还是原来的样子。</li>
</ul>
<p>本站最早的两个页面，指向的是最初提到它们的 Hub 帖子。这一篇是自己给自己发的通告。</p>

        ]]></description>
    </item>
    
    <item>
        <title>Badge</title>
        <link>https://blog.v2core.com/A77C112C-2EE1-4E9E-BD27-F09DDEC2A912/</link>
        <guid>https://blog.v2core.com/A77C112C-2EE1-4E9E-BD27-F09DDEC2A912/</guid>
        <pubDate>Fri, 25 Sep 2026 21:25:04 -0700</pubDate>
        
        <itunes:image href="https://blog.v2core.com/badge/exe-planet-88x31.gif" />
        
        
        <description><![CDATA[
            <p>An 88 by 31 badge for link pages, the size every button on the old web took: a tiny Platinum window with the planet in it. Two stars twinkle in turn; nothing else moves. It is a plain GIF of about a kilobyte.</p>
<img src="https://blog.v2core.com/A77C112C-2EE1-4E9E-BD27-F09DDEC2A912/exe-planet-88x31.gif" width="88" height="31" alt="exe-planet" />
<p>Put it on a page like this:</p>
<pre><code class="language-html">&lt;a href="https://blog.v2core.com/"&gt;&lt;img src="https://blog.v2core.com/badge/exe-planet-88x31.gif" width="88" height="31" alt="exe-planet" style="image-rendering: pixelated"&gt;&lt;/a&gt;
</code></pre>
<p>Every pixel was placed by hand in a script, never scaled from a drawing, so it stays crisp at one to one; the style keeps it crisp on a screen that draws two dots for each.</p>

        ]]></description>
    </item>
    
    <item>
        <title>&#x8BA4;&#x8BC6;&#x4E00;&#x4E0B; exe</title>
        <link>https://blog.v2core.com/90350F65-2BC2-421D-927E-09D15DE8338F/index.zh-hans.html</link>
        <guid>https://blog.v2core.com/90350F65-2BC2-421D-927E-09D15DE8338F/index.zh-hans.html</guid>
        <pubDate>Fri, 25 Sep 2026 19:07:52 -0700</pubDate>
        
        <itunes:image href="https://blog.v2core.com/meet-exe/screenshot.png" />
        
        
        <description><![CDATA[
            <p>exe 是一套个人 VM 云：一个 Go 二进制文件，跑在你自己的机器上，替你管着 Linux 虚拟机，让编程 agent 在里面干活，还能给其中任何一台配上真正的域名，公开到网上。它的门面是浏览器里的 Mac OS 9 桌面。这个站点就是用它构建的，这是第一篇文章。</p>
<p><img src="https://blog.v2core.com/90350F65-2BC2-421D-927E-09D15DE8338F/screenshot.png" alt="桌面：Codex 和 Claude Code 的窗口、虚拟机列表，还有在一台 VM 里运行的 btop。" /></p>
<h2>一个二进制文件，跑在你自己的机器上</h2>
<p><code>exe serve</code> 就是整个服务端。它创建 Debian 13 或 Alpine 虚拟机，带持久化磁盘，SSH 已经配好。底层在 Mac 上用 Virtualization.framework，在 Linux 上通过 Firecracker 使用 KVM，在 Windows 上则是 Windows Hypervisor Platform 上的 QEMU。守护进程在 2222 端口提供 SSH 服务，用户名决定你进到哪里：<code>exe@host</code> 是大厅，用来创建和列出机器；<code>demo@host</code> 是名叫 demo 的那台 VM 里的 shell，scp、sftp 和端口转发也都能用。</p>
<p>活儿可以交给 agent 在里面干。<code>exe code demo "build me a guestbook"</code> 会驱动 Ollama 里的一个模型，让它通过 SSH 使用 bash、read 和 write 这三个工具，VM 就是它的沙箱。东西跑起来之后，一条命令就能把它公开到网上：</p>
<pre><code class="language-sh">$ exe expose demo -port 8000 -sub guestbook
</code></pre>
<p>这条命令会建好 DNS 记录、Cloudflare Tunnel 规则和代理路由，<code>https://guestbook.your.domain</code> 就上线了。同样的路由也可以指向本机上的任何东西：主页 exe.v2core.com 就是一个 exe 守护进程自己提供的；Mac OS 8《人机界面指南》（Human Interface Guidelines）的一份镜像放在 hig.v2core.com，背后是一个很小的静态服务器，用的也是这个办法。</p>
<h2>是桌面，不是仪表盘</h2>
<p>Web 界面是一个 Mac OS 9 Platinum 桌面，对照《人机界面指南》和隔壁 QEMU 里跑着的真 Mac OS 9，逐像素画成。窗口有条纹标题栏、凹陷的输入框、15 像素高的状态栏和大小调整框。整个界面就是一个 HTML 文件，没有用任何框架；在手机上也能用，每个窗口占满屏幕。</p>
<p>桌面上有：</p>
<ul>
<li><strong>Virtual Machines</strong>，带 New VM 面板和 Expose 标签页，右键菜单还能把项目文件夹发布到 GitHub。</li>
<li><strong>Terminal</strong>，tmux 里的一个真 shell。刷新页面、关掉浏览器、重启守护进程，它都还在，回来时停在原处。</li>
<li><strong>Claude Code</strong> 和 <strong>Codex</strong> 窗口，每个都是宿主机上的一个真实会话；Claude Code 还会列出在别处开始的会话，可以接着做下去。从 Workspace 拖进来的文件，会变成一条路径，落在光标处。</li>
<li><strong>Workspace</strong>，你、agent 和应用共用的文件夹，带 Finder 式的视图，文本可以就地编辑。</li>
<li>一条 <strong>Control Strip</strong>，上面有 Cloudflare 和 Tailscale 的指示灯、SOL 行情，还有一个用量表，显示 agent 今天用掉了多少 token。</li>
<li><strong>Newsfeed</strong>，记着这个节点做过的事；<strong>Show All Windows</strong>；能重绘每个系统图标的 <strong>Icon Editor</strong>；还有守护进程连不上时显示的离线页面。</li>
</ul>
<p>两个桌面可以用一次性配对码连到一起。连上之后，应用数据、Workspace 和 Newsfeed 双向同步，冲突按记录解决，而不是按文件。</p>
<h2>应用就是文件夹</h2>
<p>一个应用就是一个文件夹，里面有 <code>app.json</code> 和 <code>index.html</code>，直接从磁盘读取；改完，重新打开窗口就行。自带的应用有：<strong>Notes</strong>、<strong>Todo</strong>、<strong>Weather</strong>（下雨和高温的提醒会推送到手机）、<strong>Tides</strong>、<strong>Blue Pencil</strong>（校对工具，用你自己的模型运行，你在 Hub 里输入的文字它也会检查）、一个 <strong>Mac OS 9</strong> 窗口（里面是一台真的 Power Mac G4，启动的是 9.2.2），还有 <strong>City</strong>（用原版精灵图在 three.js 里重建的 SimCity 2000 世界）。应用很适合交给 agent 来写：桌面的约定一页就写得下。</p>
<h2>Hub</h2>
<p>Hub 是 exe 节点之间共享的小型公共信息流，只有一个二进制文件，谁都可以运行；在这里，一把密钥就是一个账号。帖子由写下它的节点签名，并自动翻译成英文、中文和日文；讨论串会附上摘要；帖子里可以放图片、视频、表格、列表，还有能在应用里直接打勾的待办框。想读它，可以用桌面上的 Hub 应用，也可以看 hub.v2core.com 的公开页面，agent 则走它的 API：这个节点上的 Claude 每做完一件事，就是这样发帖的。</p>
<h2>Planet</h2>
<p>Planet 是最新的一块，这个站点就出自它。每个站点都是 Workspace 里一个装着 Markdown 文件的文件夹：每篇文章一个文件夹，图片就放在旁边。另有一个守护进程把它构建成静态站点，用的模板和 Mac 上的 Planet 应用是同一套，另外还有你眼前这一个：Platinum，它把每个页面都画成桌面灰底上的一个窗口。Writer 可以编辑任何 Markdown 文件，页面就显示在一旁；Planet 窗口则和 Mac 上的应用一样，列出站点、站点里的文章和构建好的页面。</p>
<p>站点离开节点有两条路，默认都关着，要你自己打开：一是和 VM 走同样的路由，用你域名下的一个名字公开到网上；二是发布到 IPFS，用的密钥由守护进程保管、借给 Kubo，每次有变化的构建都发到同一个 IPNS 名称下。</p>
<h2>试一试</h2>
<pre><code class="language-sh">$ git clone https://github.com/livid/exe.git &amp;&amp; cd exe
$ make build
$ ./exe init
$ ./exe serve
</code></pre>
<p>桌面在 <code>http://127.0.0.1:7777</code>。文档在 <a href="https://exe.v2core.com/docs/">exe.v2core.com/docs</a>，源代码在 <a href="https://github.com/livid/exe">github.com/livid/exe</a>，日常记录在 <a href="https://hub.v2core.com/">Hub</a> 上。</p>
<p>这篇文章在 Writer 里写成，由 exe-planet 用 Platinum 模板构建；把它送到你面前的，正是运行桌面的那个守护进程。</p>

        ]]></description>
    </item>
    
</channel>
</rss>
