tclaw(一):过年玩 OpenClaw,玩着玩着就自己造了一个

过年 2026 年春节,OpenClaw 火了。 其实年前就已经有很多人在玩了,但我那时候忙,没时间搭理。正好赶上过年,难得有几天清闲,就把 OpenClaw 装上玩了一下。 这一玩就收不住了。整个过年,家人吃饭我在玩,大年初几我也忘了,反正就是一直在玩。 玩了一段时间,自然就开始好奇它内部是怎么工作的:这东西怎么知道该调用哪个工具?记忆是怎么管理的?提示词是怎么组织的?就让 AI 帮我分析了一下源码。 发现 pi-mono 顺着 OpenClaw 的源码往里翻,发现它的内核依赖一个叫 pi-mono 的东西。 去看了 pi-mono 的代码,感觉设计很精干。它不是一个框架,只提供必要的东西:一个 Agent 循环、工具调用、会话管理,仅此而已。没有编排 DSL,没有 workflow 引擎,没有各种抽象层。核心思想就是: 把工具给大模型,让它自己决定怎么解决问题。 然后看了一下 pi-mono 的作者背景,发现是游戏开发者出身。我自己以前也做过游戏,看到这里有点感慨——牛人到哪都是牛人。 pcclaw 诞生 年后大家都在玩 OpenClaw,不知道怎么抽风了,想用 Go 实现一下 pi-mono 内核,看看它到底怎么运行的。 我平时写 Go,OpenClaw 是 JS 的,语言上的迁移借助 AI 不是太大的问题,主要还是要把原理搞清楚。2026 年 3 月 15 日,pcclaw v0.0.1 第一次提交。 pcclaw,tclaw 的前身。 架构上参考了 OpenClaw 的分层思路: tool → command → skill → agent tool:最底层,封装基础操作(bash 执行、文件读写、网络请求等) command:把 tool 组合成更高层的操作 skill:可复用的能力单元,agent 通过调用 skill 完成任务 agent:顶层,接收用户指令,通过 skill 和 tool 解决问题 Provider 层支持多种协议——OpenAI compatible、Anthropic 等,可以接不同的模型。内核沿用 pi-mono 的思路:LLM 发现问题 → 调用 tool → 检查结果 → 继续或结束。就是一个循环,没有更多了。 ...

June 2, 2026 · 1 min · 大飞

从零写OS(四十三):TCP 重传 —— 丢包了也能传完

上一章(四十二)修了一堆 busybox 相关的 bug,让 ls/exec/wait 都能正常工作,wget_test 也能跑通 HTTP。但那时的 TCP 实现有个隐患:一旦丢包,传输就会永远卡住。这一章把重传机制做完整。 原代码的问题 ch42 的 tcp_send_raw 函数身兼数职:构造 TCP 包、发送、存入发送缓冲区、推进 snd_nxt。 static void tcp_send_raw(tcp_sock_t *s, uint8_t flags, const void *data, uint16_t dlen) { ...发包... if (dlen) { ...存 sbuf... s->snd_nxt += dlen; } if (flags & (TCP_SYN | TCP_FIN)) s->seq++; // 推进 seq if (dlen) s->seq += dlen; // 又推进一次! } 问题一:seq 和 snd_nxt 是两个字段,但都在追踪"下一个要发的序号",语义重复,而且 seq 被推进了两次(SYN/FIN 一次、数据一次)。 问题二:重传时的代码非常丑陋: uint32_t saved_seq = s->seq; uint32_t saved_nxt = s->snd_nxt; s->seq = s->snd_una; s->snd_nxt = s->snd_una; tcp_send_raw(s, TCP_PSH | TCP_ACK, rtbuf, chunk); s->snd_nxt = saved_nxt; // 手动恢复 s->seq = saved_seq; 这种"临时改状态再恢复"的方式容易出错,而且没有指数退避。 ...

June 1, 2026 · 4 min · 大飞

从零写OS(四十二):让 busybox 跑起来 —— 符号链接、fork/exec、调度器 cpu_pin bug

上一章实现了 TCP/IP 栈,用户程序能发 HTTP 请求了。但验证时发现 /bin/ls 完全没反应,wget_test 也跑不起来。这一章记录排查过程——一共修了 6 个 bug,涉及 ext2 fast symlink、VFS 路径解析、内核栈溢出、缺失 syscall,以及两个调度器 cpu_pin 问题。 最终效果: / # ls bin etc lost+found / # cd bin /bin # ls busybox cp kill mv pwd sh wget_test cat echo ls ps rm umount /bin # wget_test wget_test start connecting... connected! request sent HTTP/1.0 200 OK ... DONE /bin # 背景:busybox 的目录结构 Makefile 用这种方式制作 ext2 镜像: sudo cp busybox-x86_64 /tmp/ext2mnt/bin/busybox sudo cp busybox-x86_64 /tmp/ext2mnt/bin/sh # sh 是真实复制 for cmd in ls cat echo pwd ...; do sudo ln -sf /bin/busybox /tmp/ext2mnt/bin/$cmd # 其他命令是符号链接 done /bin/sh 是真实文件,/bin/ls 等是指向 /bin/busybox 的符号链接。 ...

June 1, 2026 · 4 min · 大飞

用 tclaw 做了 6 个小游戏

最近在用自己写的 AI 工具 tclaw 做一些实验,让它帮我写了几个纯 HTML 小游戏。 没想到效果挺不错的——贪吃蛇、俄罗斯方块、2048、Flappy Bird、太空侵略者、青蛙过马路,全部跑在浏览器里,不需要安装任何东西。 → 点这里玩 这几个游戏是通过 tbrain 多 agent 协作完成的:tbrain 负责把任务拆解成子任务,分配给不同的 agent 并行开发,最后汇总结果。整个过程我只提了一句需求,剩下的规划、开发、测试都是 agent 自己跑完的。 所有游戏都是单个 HTML 文件,JS/CSS 全部内联,纯静态,没有服务器逻辑。基本没有人工修改。 有点感慨:以前写这种东西要花好几个小时,现在十几分钟出来六个。

June 1, 2026 · 1 min · 大飞

GitHub 开源爬虫与信息订阅工具全览

想爬数据、订阅信息源、聚合内容?这里整理了 GitHub 上常见的开源爬虫与信息订阅工具,按类别分组,标注了是否需要登录、实现原理、可获取的内容,方便选型。 爬虫框架 项目 语言 实现原理 可爬取内容 是否需要登录 登录方式 Stars 维护状态 部署难度 适用场景 Playwright TS/Python/Java 控制真实浏览器,完整JS渲染 任意网页内容,含动态渲染(自定义) ❌ 不需要 视目标站而定 89k 活跃 低 JS渲染页面、模拟用户行为、绕过反爬 Scrapy Python Twisted异步,XPath/CSS选择器,中间件+Pipeline架构 任意结构化网页数据(自定义) ❌ 不需要 视目标站而定 62k 活跃 中 大规模结构化数据采集 Crawlee TypeScript 封装Playwright/Puppeteer/Cheerio,内置请求队列+代理轮换 任意网页内容,含SPA(自定义) ❌ 不需要 视目标站而定 23k 活跃 低 Node.js生态爬虫,SPA网站采集 社交媒体爬虫 项目 语言 实现原理 可爬取内容 是否需要登录 登录方式 Stars 维护状态 部署难度 适用场景 MediaCrawler Python Playwright控制浏览器,逆向平台API签名,异步并发 帖子/视频标题、正文、图片、视频、点赞/收藏/转发数、评论(含回复)、用户信息、话题标签 ⚠️ 部分需要 扫码/Cookie注入 50k 活跃 中 社交媒体内容+评论批量采集、舆情分析 Douyin_TikTok_Download_API Python 逆向抖音/TikTok API签名算法,FastAPI对外提供接口 视频(无水印)、封面、描述、点赞/评论/分享数、作者信息、音乐信息 ⚠️ 部分需要 Cookie注入 18k 活跃 低 视频无水印下载,API集成 dataabc/weibo-crawler Python 请求微博移动端API,解析JSON,多种存储后端 微博正文、图片、视频、发布时间、点赞/转发/评论数、用户信息、话题 ⚠️ 部分需要 Cookie注入 4.5k 较活跃 低 微博用户内容存档 videodl Python 逆向各平台API获取真实视频地址,FFmpeg合并 视频文件(无水印)、封面图、视频标题 ⚠️ 部分需要 Cookie注入 2.1k 一般 低 多平台视频存档 lxSpider Python 各平台独立实现,含Requests/Selenium/Scrapy多方案 各平台商品/评论/用户/内容数据(视具体案例) ⚠️ 部分需要 各平台不同 2k 一般 低 爬虫学习参考 微信公众号 项目 语言 实现原理 可爬取内容 是否需要登录 登录方式 Stars 维护状态 部署难度 适用场景 WeChatRobot C++ Windows DLL注入Hook微信进程,访问本地加密数据库 聊天记录、公众号文章、联系人、群组、本地加密数据库 ✅ 需要 微信客户端登录(仅Windows) 7.1k 一般 极高 微信数据深度采集、机器人开发 WechatSogou Python HTTP请求搜狗微信公开接口,BeautifulSoup解析 公众号名称/简介/头像、文章标题/摘要/链接/发布时间 ❌ 不需要 - 6.3k 停止维护 低 公众号内容搜索聚合 wechat_articles_spider Python mitmproxy中间人代理拦截微信客户端流量 公众号历史文章全量(标题、正文、发布时间、阅读数、点赞数、原文链接) ✅ 需要 微信客户端登录+抓包 3.4k 一般 高 公众号历史文章全量存档 we-mp-rss Python 微信账号授权后调用公众号接口,转换RSS输出 公众号文章标题、摘要、正文、发布时间、封面图,转为RSS Feed ✅ 需要 微信账号授权 3.2k 活跃 中 将公众号纳入RSS阅读器统一订阅 新闻爬虫 项目 语言 实现原理 可爬取内容 是否需要登录 登录方式 Stars 维护状态 部署难度 适用场景 newspaper3k Python HTTP请求+lxml解析正文,NLP提取摘要/关键词 文章正文、标题、作者、发布时间、摘要、关键词 ❌ 不需要 - 15k 停止维护 低 学习参考,生产建议用4k news-please Python Scrapy驱动,自动解析RSS/Sitemap,结构化存储 文章正文、标题、作者、发布时间、描述、图片、语言、来源域名 ❌ 不需要 - 2.5k 较活跃 中 大规模新闻数据集构建、学术研究 NewsCrawl Python Scrapy+Redis+Celery分布式,定时任务+监控面板 文章标题、正文、发布时间、来源、分类 ❌ 不需要 - 671 一般 高 企业级舆情监控 NewsCrawler Python Playwright浏览器自动化,覆盖中外媒体 文章标题、正文、发布时间、作者、来源平台 ⚠️ 部分需要 Cookie注入 417 活跃 中 中外媒体跨语言新闻聚合 newspaper4k Python HTTP请求+lxml解析,NLP提取,支持异步 文章正文、标题、作者、发布时间、摘要、关键词、顶部图片 ❌ 不需要 - 1.1k 活跃 低 快速提取任意新闻正文 RSS 阅读器 / 信息聚合 项目 语言 实现原理 可爬取内容 是否需要登录 登录方式 Stars 维护状态 部署难度 适用场景 Glance Go 单二进制,定时拉取各平台API,无数据库 RSS文章、Reddit帖子、HN热帖、GitHub Release、YouTube视频、天气、股票 ❌ 不需要 部分源需API Key 34k 活跃 极低 个人信息看板 FreshRSS PHP 定时拉取RSS/Atom feed,兼容Google Reader/Fever API RSS/Atom订阅源的文章标题、正文、发布时间、作者、链接 ❌ 不需要 - 15k 活跃 中 自托管RSS服务,多用户共享 Miniflux Go 轻量HTTP服务+PostgreSQL,定时抓取RSS RSS/Atom订阅源的文章标题、正文、发布时间、作者、链接、附件 ❌ 不需要 - 9.3k 活跃 低 极简高性能RSS,键盘流用户 RSSbrew Python 拉取RSS后过滤+调用OpenAI生成摘要,输出新Feed RSS源文章,经过滤/AI摘要后重新输出为新RSS ❌ 不需要 OpenAI API Key 287 较活跃 低 RSS内容过滤与AI摘要提炼 选型建议 爬取国内社交媒体(小红书/抖音/微博/B站)→ MediaCrawler,覆盖最全,维护最活跃 订阅微信公众号 → we-mp-rss 转成 RSS,配合 Miniflux 或 FreshRSS 统一阅读 自建 RSS 服务 → 极简选 Miniflux,功能全选 FreshRSS 个人信息聚合看板 → Glance,一个 Docker 命令搞定 提取任意新闻正文 → newspaper4k,3 行代码搞定 自定义爬虫开发 → Python 用 Scrapy,JS 网站加 Playwright;Node.js 用 Crawlee 下载抖音/TikTok 视频 → Douyin_TikTok_Download_API,有完整 REST API

May 26, 2026 · 2 min · 大飞

语音克隆(二):主流开源项目全景对比

目前开源语音克隆项目百花齐放,本文整理了 GitHub 上最热门的项目,对比各自的架构、语言支持、适用场景,帮你快速选型。 Stars 排行榜 排名 项目 Stars 核心特点 1 Real-Time-Voice-Cloning ~60k 经典三阶段流水线,最早流行的克隆项目 2 GPT-SoVITS ~58k 中文最强,1分钟数据即可微调 3 Coqui TTS (XTTS) ~45k 工业级框架,17种语言,3秒零样本 4 ChatTTS ~39k 中文对话语音质量领先,支持笑声停顿等 5 Bark ~39k 创意音频,可生成笑声/哭声/背景音效 6 MockingBird ~37k 中文版 Real-Time-Voice-Cloning 7 OpenVoice ~37k 音色迁移架构,推理极快 8 RVC ~36k 歌声转换首选,支持实时变声 9 Fish Speech ~31k 端到端,多语言,工业级质量 10 so-vits-svc ~28k AI翻唱鼻祖,歌声克隆质量极高 11 Chatterbox ~25k Resemble AI开源,情感可控 12 CosyVoice ~21k 阿里出品,LLM+流匹配,5种语言 13 Index-TTS ~21k bilibili出品,工业级稳定 14 F5-TTS ~15k 流匹配,非自回归,推理快 15 OmniVoice ~6.6k 支持600+语言,扩散语言模型 完整对比表 项目 架构 支持语言 零样本克隆 推理速度 需要训练 最适合场景 Real-Time-Voice-Cloning 三阶段流水线 英文 是(5s) 接近实时 否 学习/原型验证 GPT-SoVITS GPT + VITS 中/英/日 是(可微调) 中等 可选 中文配音首选 Coqui TTS 多架构框架 17种 是(3s) 中等 否 多语言生产部署 Bark 自回归LM 13种 弱 慢 否 创意/情感音频 ChatTTS 生成式LM 中/英 是 中等 否 中文对话TTS MockingBird 三阶段流水线 中/英 是(5s) 接近实时 否 中文克隆 OpenVoice 音色迁移 6种 是 极快 否 快速克隆部署 RVC VITS + 特征检索 语言无关 需少量训练 实时 是(<10min) 歌声/实时变声 Fish Speech 端到端AR + VQGAN 8+种 是(10s) 快 否 高质量多语言 so-vits-svc SoftVC + VITS 语言无关 需训练 中等 是 AI翻唱 Chatterbox s3gen + 扩散 英文 是 快 否 英语情感配音 CosyVoice LLM + 流匹配 中/英/日/粤/韩 是(3-10s) 快 否 商业TTS服务 Index-TTS GPT-style 中/英 是 快 否 工业生产 Tortoise TTS 自回归 + 扩散 英文 是 慢 否 高质量英语有声书 F5-TTS 流匹配 DiT 中/英 是 快 否 快速零样本克隆 StyleTTS2 扩散 + SLM 英文 是 中等 否 英语质量基准 VALL-E-X 神经编解码LM 英/中/日 是 中等 否 跨语言克隆 Kokoro StyleTTS2变体 英+中日韩法 否(固定音色) 极快 否 本地轻量部署 OmniVoice 扩散语言模型 600+种 是 快 否 超多语言 EmotiVoice BERT + TTS 中/英 有限 中等 否 情感化中文TTS VoiceCraft 自回归 + 码书重排 英文 是 中等 否 语音片段编辑 Qwen3-TTS LLM-native 多语言 是 中等 否 与LLM集成 MetaVoice 自回归 + 扩散(1B) 英文 是(30s) 中等 否 高质量英语克隆 Parler-TTS 描述控制TTS 英文 文本描述控制 中等 否 可控TTS研究 ZipVoice 流匹配 + 蒸馏 中/英 是 极快 否 低延迟实时TTS ESPnet 多架构工具包 多语言 有 依模型 通常需要 学术研究 按使用场景推荐 中文语音克隆 GPT-SoVITS > ChatTTS > CosyVoice > Index-TTS ...

May 26, 2026 · 2 min · 大飞

语音克隆(一):用 OmniVoice 克隆任意声音

想让 AI 用你的声音说话?只需要一段 3 到 10 秒的录音,OmniVoice 就能克隆你的声音,说出任意文字。 OmniVoice 是什么 OmniVoice 是小米 / k2-fsa 团队开发的开源零样本 TTS 模型,支持 600+ 种语言,基于扩散语言模型架构,推理速度极快(RTF 最低 0.025,比实时快 40 倍)。 支持三种模式: 语音克隆:提供参考音频,克隆声音说出任意文字 语音设计:用文字描述声音(性别、年龄、音调、口音等) 自动语音:模型自动选择声音 环境准备 安装 conda 环境 conda create -n omnivoice python=3.11 -y conda activate omnivoice 安装 PyTorch # Apple Silicon pip install torch==2.8.0 torchaudio==2.8.0 # NVIDIA GPU(以 CUDA 12.8 为例) pip install torch==2.8.0+cu128 torchaudio==2.8.0+cu128 --extra-index-url https://download.pytorch.org/whl/cu128 安装 OmniVoice git clone https://github.com/k2-fsa/OmniVoice.git cd OmniVoice pip install -e . 下载模型 第一次运行会自动下载。如果在国内连不上 HuggingFace,设置镜像: ...

May 25, 2026 · 1 min · 大飞

从零写OS(三十七):网络栈 —— e1000 驱动 + ARP/IP/TCP + Socket

文件系统能读写了,这一章加网络支持。目标是实现一个最小 TCP/IP 栈,让用户程序能通过 socket 发送 HTTP 请求并收到响应。 验证方式: / # wget_test wget_test start connecting... connected! request sent HTTP/1.0 200 OK ... DONE 架构概览 用户程序(wget_test) ↕ syscall: socket/connect/write/read/close 内核 socket 层(net.c) ↕ tcp_connect / tcp_send / tcp_recv / tcp_close TCP 层(net.c) ↕ 以太网帧收发 ARP 层(net.c) ↕ e1000_send / e1000_recv e1000 网卡驱动(e1000.c) ↕ MMIO + DMA QEMU e1000 虚拟网卡(-netdev user,id=net0 -device e1000,netdev=net0) PCI 枚举 e1000 通过 PCI 总线连接。内核在启动时枚举 PCI 设备: void pci_enumerate(void) { for (bus=0; bus<256; bus++) for (dev=0; dev<32; dev++) for (fn=0; fn<8; fn++) { uint16_t vendor = pci_read16(bus, dev, fn, 0); if (vendor == 0xFFFF) continue; // 记录 vendor/device/bar0 } } e1000 的 vendor=0x8086,device=0x100E。BAR0 是 MMIO 基地址(通常 0xFEBC0000)。 ...

May 22, 2026 · 4 min · 大飞

从零写OS(三十六):ext2 写操作 —— 文件创建、引用计数与 tty 字符设备

前几章文件系统都是只读的。这一章实现 ext2 的写路径,让 echo hello > /tmp/a.txt && cat /tmp/a.txt 能正常工作,且重启后文件仍然存在。过程中还修了 fd 引用计数和 tty 字符设备两个问题。 ext2 磁盘结构回顾 块组 0: [超级块][组描述符][block bitmap][inode bitmap][inode table][数据块...] 关键字段: sb->s_free_inodes_count / gd->bg_free_inodes_count:空闲 inode 计数 sb->s_free_blocks_count / gd->bg_free_blocks_count:空闲 block 计数 gd->bg_inode_bitmap:inode bitmap 所在块号 gd->bg_block_bitmap:block bitmap 所在块号 gd->bg_inode_table:inode table 起始块号 inode 号从 1 开始;前 10 个是系统保留的(root=2,lost+found=11)。 alloc_inode / alloc_block alloc_inode uint32_t alloc_inode(void) { // 1. 读 inode bitmap 块 // 2. 找第一个为 0 的位(bit i → inode i+1) // 3. 置位,写回 bitmap // 4. 更新超级块和组描述符的 free_inodes_count // 5. 返回 inode 号(从 1 开始) } alloc_block uint32_t alloc_block(void) { // 1. 读 block bitmap 块 // 2. 找第一个为 0 的位,跳过 block 0(保留) // 3. 置位,写回 bitmap // 4. 更新超级块和组描述符的 free_blocks_count // 5. 清零新分配的块(避免垃圾数据) // 6. 返回块号 } 注意:block bitmap 的 bit 0 对应 block 0,必须跳过(block 0 不存在)。实际第一个可分配的块由文件系统布局决定(本项目中是 610)。 ...

May 22, 2026 · 3 min · 大飞

从零写OS(三十五):getdents64 + chdir + 内存屏障 Bug

上一章 ls 能运行了,但打印出来的目录内容是空的——因为还没有实现 getdents64。这一章把目录列表、cd、pwd 全部补齐,同时碰到了一个 -O2 下内存乱序导致的调度器死循环 Bug。 SYS_GETDENTS64 Linux 接口 int getdents64(int fd, struct linux_dirent64 *dirp, unsigned int count); 每个条目的结构: struct linux_dirent64 { uint64_t d_ino; // inode 号 int64_t d_off; // 到下一条目的偏移(可用递增序号代替) uint16_t d_reclen; // 本条目总字节数(含填充,8 字节对齐) uint8_t d_type; // 文件类型(4=目录,8=普通文件) char d_name[]; // 文件名(null 结尾) }; d_reclen 必须 8 字节对齐,计算方式: uint16_t reclen = (uint16_t)((19 + namelen + 1 + 7) & ~7); // ↑固定头部 ↑名字 ↑null ↑对齐 内核实现 在 VFS 层实现 vfs_getdents,遍历 ext2 目录的所有条目,逐个填写 linux_dirent64 并写入用户缓冲区: int vfs_getdents(int fd, uint64_t uva, uint32_t count) { // 1. 检查 fd 是否为目录 // 2. 从 offset 开始遍历 ext2 目录 // 3. 跳过 "." 和 ".."(busybox ls 不显示它们) // 4. 每个条目:填 d_ino、d_type、d_name、d_reclen // 5. 通过 copy_to_user 写入用户空间 // 6. 更新 file->offset,返回写入的总字节数 } 关键:返回 0 表示目录已读完(EOF),busybox ls 据此停止调用。 ...

May 22, 2026 · 3 min · 大飞
京ICP备14031575号-3