jcode 深度拆解:28MB 内存跑 Coding Agent、14ms 启动、记忆图谱与 Swarm 协作,一个人用 Rust 写出的「反 Electron 宣言」
一、背景:当 Coding Agent 集体变成「内存黑洞」
2026 年 7 月 22 日,一个叫 1jehuang/jcode 的仓库登上 GitHub Trending 日榜,Star 数突破 10k。作者 Jeremy Huang 一个人用 Rust 写了 9.2 万行代码,给这个项目起了个直白到近乎挑衅的口号:
The most RAM efficient harness. The most intelligent harness.
「最省内存的 Harness,最聪明的 Harness」——两个 most 叠在一起,火药味十足。
要理解 jcode 为什么火,得先看看 Coding Agent 赛道现在的「体重问题」。作者在 README 里放了一组用 PSS(Proportional Set Size,比 RSS 更公平的多进程内存指标)实测的数据,单会话空闲状态:
| 工具 | PSS 内存 | 相对 jcode |
|---|---|---|
| jcode(关闭本地嵌入) | 27.8 MB | 基线 |
| Codex CLI | 140.0 MB | 5.0× |
| pi | 144.4 MB | 5.2× |
| Cursor Agent | 214.9 MB | 7.7× |
| GitHub Copilot CLI | 333.3 MB | 12.0× |
| OpenCode | 371.5 MB | 13.4× |
| Claude Code | 386.6 MB | 13.9× |
单会话差距已经够大了,但真正拉开差距的是多会话场景。同时开 10 个活跃会话:
| 工具 | 10 会话 PSS | 相对 jcode |
|---|---|---|
| jcode(关闭本地嵌入) | 117.0 MB | 基线 |
| Codex CLI | 334.8 MB | 2.9× |
| Antigravity CLI | 1021.2 MB | 8.7× |
| Cursor Agent | 1632.4 MB | 14.0× |
| GitHub Copilot CLI | 1756.5 MB | 15.0× |
| Claude Code | 2300.6 MB | 19.7× |
| OpenCode | 3237.2 MB | 27.7× |
Claude Code 跑 10 个会话吃掉 2.3GB,OpenCode 直接干到 3.2GB——而 jcode 只要 117MB,每增加一个会话边际成本约 9.9MB(Claude Code 是 ~212.7MB/会话,21.5 倍差距)。
启动速度同样夸张。Time to first frame(首帧渲染时间):jcode 14.0ms,Claude Code 3436.9ms,245 倍差距。你按下回车,jcode 已经画完界面了,Claude Code 的 Node.js 运行时可能还没加载完。
这组数字背后是一个被行业刻意忽视的事实:主流 Coding Agent 几乎全是 Node.js/TypeScript 写的,而 JS 运行时的内存模型天然不适合「多实例常驻」场景。当你的工作流从「开一个 Agent 干活」进化到「开一群 Agent 并行干活」,运行时开销就从「可以忍」变成「忍不了」。
jcode 的答案是:零运行时依赖,纯 Rust,静态二进制。本文就来拆解这套「反 Electron 宣言」是怎么落地的——不只是省内存这种表面功夫,还有它真正的护城河:语义记忆图谱和 Swarm 多智能体协作。
二、核心架构:为什么 Rust Harness 能做到 20 倍内存差距
2.1 Harness 到底是什么
先统一术语。Coding Agent 领域说的 Harness(马具/挽具),指的是包裹在 LLM 外面的那层工程壳:终端 UI、工具执行器、上下文管理、会话持久化、权限控制。模型负责「想」,Harness 负责「干」——读写文件、跑命令、抓网页、管理记忆,全是 Harness 的活。
同样接 Claude 的 API,不同 Harness 的实际产出可以差出一个档次。这就是作者说「raise the skill ceiling」的底气:模型是租来的,Harness 才是自己的。
2.2 内存效率的三层来源
jcode 的低内存不是某个单点优化,而是三层叠加:
第一层:没有运行时税。 Node.js 进程起步就是 40-80MB(V8 堆、JIT 缓存、libuv 线程池),Electron 更是 200MB 起。Rust 编译出的静态二进制没有 GC、没有 JIT、没有解释器,空跑就是几 MB。这一层白捡 100MB+。
第二层:客户端-服务器架构的会话复用。 jcode 支持 jcode serve 后台服务模式 + jcode connect 多客户端接入。10 个会话不是 10 个完整进程,而是一个服务进程管理 10 份会话状态,客户端只是轻量的 TUI 渲染器。这就是「每会话边际成本 9.9MB」的秘密——增量只有会话状态本身,没有重复的运行时。
对比之下,Claude Code 每开一个会话就是一个完整的 Node 进程,212MB 的边际成本里绝大部分是重复加载的运行时和依赖。
第三层:渲染层的极限优化。 jcode 的 TUI 帧渲染耗时 0.67ms,理论上能跑 1400+ FPS。作者为此做了两件在旁人看来近乎偏执的事:
- 重写 Mermaid 渲染器。 原版 Mermaid 依赖浏览器和 TypeScript,作者用 Rust 写了 mermaid-rs-renderer,渲染速度快 1800 倍,零浏览器依赖,让流程图能直接内联渲染在终端聊天流里。
- 自己写了个终端。 因为传统终端的 scrollback 机制无法实现平滑的部分行滚动,作者干脆开了个新项目 Handterm,实现原生 scroll API。
一个人为了终端滚动体验去写终端模拟器——这种工程密度,是这个项目最「Rust 社区」的地方。
2.3 工程体感:快到改变使用习惯
这些数字翻译成日常体验是什么?
- 即开即用:14ms 首帧 + 48.7ms 可输入,jcode 快到可以当
grep一样随手开随手关。而 Claude Code 3.4 秒的启动时间,会让你下意识地「攒够了问题再开」。 - 多会话自由:在 8GB 内存的开发机或者 VPS 上同时开 10 个会话毫无压力。SSH 到服务器上跑 Agent,jcode 是目前体验最好的选择之一。
- 无 flicker:1400 FPS 的渲染上限意味着无论终端刷新多频繁都不会闪烁撕裂。
工具性能好到一定程度,会反过来改变工作流的形态。这是 jcode 后面两个大杀器(记忆和 Swarm)的物理基础:只有会话足够便宜,你才养得起一群 Agent。
三、语义记忆图谱:不用向量数据库的「人类式记忆」
如果说内存效率是 jcode 的门面,记忆系统就是它的灵魂。主流 Coding Agent 的记忆现状是:Claude Code 每次会话从零开始(靠 CLAUDE.md 手工维护),Codex CLI 没有跨会话记忆。jcode 则内置了一套完整的语义记忆图谱。
3.1 设计哲学:被动召回,而非主动查询
jcode 记忆系统最反直觉的设计是:Agent 不需要主动调用记忆工具。
工作原理:每一轮对话(turn/response)都会被嵌入成语义向量。每个新 turn 到来时,系统自动用当前上下文的嵌入向量去记忆图里做余弦相似度检索,命中的记忆被直接注入对话上下文——或者先经过一个 Memory SideAgent(记忆侧车代理)验证相关性后再注入。
这模拟的是人类记忆的工作方式:你不会「主动执行一次回忆操作」,相关记忆是被当前情境自动唤起的。相比让主 Agent 反复调用 search_memory 工具,这种被动注入既省 token,又不打断推理流。
同时,显式的记忆工具依然保留(主动存储/检索),加上对历史会话的传统 RAG 搜索,构成「被动召回为主、主动查询兜底」的双轨制。
3.2 存储层:JSON 文件 + petgraph,拒绝向量数据库
技术选型上,jcode 做了一个很「本地优先」的决定:不接 Pinecone/Qdrant/Weaviate 任何外部向量库。
- 嵌入模型:
all-MiniLM-L6-v2,通过tract-onnx在本地 CPU 推理(这也是「关闭本地嵌入可省 140MB 内存」的来源) - 向量检索:内存中直接算余弦相似度
- 图结构:
petgraph::DiGraph有向图
存储布局全是人类可读的 JSON:
~/.jcode/memory/
├── graph.json # 序列化的 petgraph 有向图
├── global.json # 用户全局记忆
├── projects/
│ └── <project_hash>.json # 按项目隔离的记忆
├── embeddings/
│ └── <memory_id>.vec # 每条记忆的嵌入向量
├── clusters/
│ └── cluster_metadata.json # HDBSCAN 聚类中心
└── tags/
└── tag_index.json # 标签索引
核心数据结构(来自项目的 MEMORY_ARCHITECTURE.md):
pub struct MemoryGraph {
graph: DiGraph<MemoryNode, EdgeKind>, // petgraph 有向图
memory_index: HashMap<String, NodeIndex>, // 快速查找索引
tag_index: HashMap<String, NodeIndex>,
cluster_index: HashMap<String, NodeIndex>,
}
pub enum MemoryNode {
Memory(MemoryEntry), // 记忆本体:内容 + 嵌入 + 元数据
Tag(TagEntry), // 显式标签节点
Cluster(ClusterEntry), // HDBSCAN 自动聚类节点
}
pub enum EdgeKind { // 六种边关系
HasTag,
RelatesTo { weight: f32 },
Supersedes, // 新记忆取代旧记忆
Contradicts, // 冲突标记
InCluster,
DerivedFrom,
}
注意 Supersedes 和 Contradicts 这两种边——记忆不是只增不减的日志,而是一个会自我修正的知识结构。新的事实可以取代旧的,矛盾会被显式标记出来等待消解。
3.3 检索流程:嵌入检索 + 图扩散 + 侧车验证
单纯的向量 top-k 检索有个老问题:语义相似 ≠ 逻辑相关。jcode 用四步级联缓解:
Step 1: 嵌入相似度搜索 → 取 top-10 种子节点
Step 2: BFS 图遍历(深度 2)
从种子节点沿边扩散,不同边类型不同权重:
HasTag 0.8 / InCluster 0.6 / RelatesTo 按实际权重 / Supersedes 0.9
衰减公式:decayed_score = edge_weight × 0.7^depth
Step 3: 轻量侧车模型验证关联性(可选)
Step 4: 去重、排序,返回最终 top-10
第二步的图扩散是精髓:向量检索负责「捞相似的」,图遍历负责沿着显式关系把逻辑相关但语义不相似的记忆也带出来。比如「用户偏好 pnpm」这条记忆,可能和当前讨论的构建报错在向量空间里相距很远,但通过 RelatesTo 边一跳就能到达。
3.4 记忆的新陈代谢:半衰期与后台巩固
jcode 把记忆分为四类,各自有不同的信心半衰期:
| 记忆类型 | 半衰期 | 设计逻辑 |
|---|---|---|
| Correction(修正) | 365 天 | 用户纠正过的错误最不该忘 |
| Preference(偏好) | 90 天 | 偏好会变,但变得慢 |
| Fact(事实) | 30 天 | 项目事实迭代快 |
| Inferred(推断) | 7 天 | Agent 自己猜的,最不可靠 |
这个梯度设计很有讲究:记忆的可信度和它的来源强相关。用户明确说「不对,应该用 X」的修正权重最高衰减最慢;Agent 从上下文里自己推断出来的结论,7 天就基本失效——因为推断最容易过时也最容易出错。
记忆的写入侧同样自动化:每隔一段时间(语义漂移检测、距上次提取 K 轮、会话结束等触发条件),Memory SideAgent 从对话里提取值得记住的内容写入图谱。后台的 ambient mode 还会周期性地做记忆巩固——合并重复、消解矛盾、验证过期信息、HDBSCAN 重聚类。作者的类比是睡眠中的记忆巩固:你休息时,大脑在整理白天的经历。
从工程视角看,这套系统给了我们一个重要启示:Agent 记忆不需要重型基础设施。一个 22MB 的 ONNX 嵌入模型 + petgraph + JSON 文件,就能实现比多数云端方案更精细的记忆语义。本地优先,人类可读,用户可以直接打开 JSON 改记忆——这比任何「记忆管理后台」都直接。
四、Swarm:不需要编排器的多 Agent 协作
多 Agent 协作是 2026 年的顶流话题,但多数方案是「框架级」的:你要写 DAG、定义节点、编排工作流。jcode 的 Swarm 走了另一条路:协作能力内化在 Harness 里,Agent 之间像同事一样自组织。
4.1 三层角色与一条铁律
根据项目的 SWARM_ARCHITECTURE.md,Swarm 是严格的三级分工:
用户
│
▼
协调者 (Coordinator) ← 唯一面向用户的入口
│
├── 工作树管理器 (WTM) ← 可选,管理一个 git worktree
│ ├── Agent 1
│ └── Agent 2
└── 工作树管理器 (WTM)
├── Agent 3
└── Agent 4
- 协调者:唯一能生成/关闭 Agent 的角色;制定 Plan、审批 Plan 变更;但不负责合并代码
- WTM:管理一个 git worktree,负责该范围内的集成
- Agent:并行干活,不能生成或关闭其他 Agent,可以直接和同伴协商
一条铁律:Agent 不能链式生成。A 生成了 B,B 就不能再生成 C。这条约束看似保守,实际上掐灭了多 Agent 系统最危险的失控模式——指数级的 Agent 繁殖和失去控制的调用树。整个系统永远是一棵深度可控的树。
4.2 通信:软中断,而不是轮询
Agent 间通信靠 Comms Router(通信路由器)+ 通知队列,支持五种通道:
| 通道 | 类型 | 场景 |
|---|---|---|
| DM | 点对点私信 | 两个 Agent 直接协商冲突 |
| Swarm Broadcast | 全员广播 | 生命周期事件、全局状态 |
| Topic Channels | 主题群聊 | 多方围绕特定话题讨论 |
| Shared Context Keys | 共享键值 | set/read/append 共享状态 |
| Channel Discovery | 频道发现 | 找到相关频道和参与者 |
最值得细品的设计是软中断投递:通知在 Agent 的安全点(safe point)注入,消息可以穿插进当前 turn,不需要等 Agent 忙完再开新 turn。这解决了多 Agent 系统的经典延迟问题——「B 修改了你在改的文件」这种消息如果要等当前任务做完才能收到,冲突早就发生了。
读取其他 Agent 的上下文分三档,防止 token 爆炸:
- Status Snapshot:元数据 + 当前工具快照,极轻,目标 Agent 忙碌时也能读
- Summary Feed:工具调用名 + 意图 + 简要结果
- Full Context:完整上下文,重量级,谨慎使用
4.3 冲突处理:去中心化协商
Swarm 最出彩的机制是文件触碰通知(File Touch Notification):当 Agent A 编辑了 Agent B 已经读过的文件(「代码在脚下移动」),服务器立即通知 B。B 可以忽略(不相关),也可以查 diff 确认没有冲突。
关键在于:冲突协商不经过协调者。A 和 B 直接 DM 商量。协调者不是中央调度器,不插手执行细节,它只管四件事:分解任务、生成 Agent、审批 Plan 更新、处理失败(retry / reassign / replace / salvage 四种恢复策略)。
完整任务流转是这样的:
用户 → 协调者(制定 Plan v1,内存对象,不落仓库文件)
→ 生成 Agent + 分发 scope
→ Agent 并行执行(冲突时自行 DM 协商)
→ Agent 发现 Plan 有问题 → propose update → 协调者审批 → 广播
→ 完成报告(outcome / changes / validation / blockers 四要素强制)
→ 各 WTM 负责 worktree 内集成(协调者不 merge)
Agent 生命周期是一个显式状态机:
spawned → ready → running ⇄ blocked → completed → stopped
↘ failed → crashed
这套设计的成熟之处在于它像一个运转良好的工程团队,而不是一个流水线:Tech Lead(协调者)分任务但不盯着每行代码,工程师(Agent)遇到冲突自己去和同事对齐,模块负责人(WTM)管好自己那摊集成。相比之下,需要预定义 DAG 的编排框架更像是流水线——高效,但僵硬。
而这一切的前提,又绕回了第二章:每个 Agent 只占 ~10MB 边际内存。如果每个 Agent 都是 200MB 的 Node 进程,「随手 spawn 一个团队」根本无从谈起。性能不是虚荣指标,是架构可能性的地基。
五、上手实战
5.1 安装与启动
# macOS / Linux 一键安装
curl -fsSL https://jcode.sh/install | bash
# Windows 11 (PowerShell 5.1+)
irm https://jcode.sh/install.ps1 | iex
# 源码编译(需要 Rust 工具链)
git clone https://github.com/1jehuang/jcode.git && cd jcode
cargo build --release && scripts/install_release.sh
常用启动方式:
jcode # 交互式 TUI
jcode run "写一个 hello world" # 非交互单次执行
jcode --resume fox # 恢复历史会话(会话有代号)
jcode serve # 后台服务模式
jcode connect # 客户端接入已有服务
5.2 模型接入:订阅党福音
jcode 内置 11+ 种 OAuth 登录流,已有订阅可以直接复用,不用额外买 API 额度:
jcode login --provider claude # Claude Max 订阅
jcode login --provider openai # ChatGPT / Codex 订阅
jcode login --provider gemini # Google Gemini
jcode login --provider copilot # GitHub Copilot
jcode login --provider ollama # 本地 Ollama
jcode login --provider openai-compatible # 任意兼容端点,支持 localhost 免密钥
最后一项对隐私敏感团队很关键:接一个内网自托管的 vLLM/LM Studio 端点,全链路(模型推理 + 嵌入计算 + 记忆存储)都不出内网。
5.3 值得一试的特性
- 侧边栏:让 Agent 把文件加载进 side panel 实时刷新,或直接当 diff 查看器;聊天流内联渲染 Mermaid 图
- Plan Mode:先只读探索、呈现计划,批准后才动手改文件——大重构的安全带
- Self-Dev 模式:Agent 修改 jcode 自身源码并自动构建热重载。项目相当比例的代码就是 jcode 自己写的,「哪里不爽改哪里」在这个项目里是字面意思
- Swarm 试用:同一个仓库开两个 jcode 会话,它们会被 server 自动纳入协作管理;或者直接让 Agent 用 swarm 工具自己拉团队
六、冷静的边界分析
吹完了,泼点冷水。以下几点在选型前必须想清楚:
1. Benchmark 由作者自测,未经第三方独立验证。 PSS、首帧时间这些数据方法论看起来严谨(10 次 PTY 启动取样、标注对比版本号),但毕竟是 README 里的自家数字。竞品版本也在快速迭代,数字的保鲜期有限。
2. 单人项目的巴士系数。 9.2 万行 Rust,148 个 open issue,核心贡献者一个人。项目处于活跃开发期(版本号 v0.9.x-dev),API 随时可能 Breaking Change。把它引入团队关键路径之前,掂量一下维护风险。
3. 智能上限依然由模型决定。 Harness 优化的是「工程下限」和「上下文质量」,写代码的还是背后的 Claude/GPT/Gemini。jcode 不会让一个弱模型变强,它只是让强模型少受工程拖累。
4. 记忆系统是双刃剑。 自动注入的记忆如果过时或错误(尤其是 Inferred 类),会静默污染上下文。虽然有半衰期和巩固机制兜底,但「Agent 记住了三周前的错误结论」这类问题排查起来比无状态系统更隐蔽。
5. Rust 门槛拦住了贡献者。 对比 TypeScript 系项目,能给 9 万行 Rust 提 PR 的社区成员少得多。生态插件的繁荣度大概率不如 Claude Code 生态。
适合谁:SSH/服务器远程开发、低配机器、多项目并行、想要跨会话记忆、隐私敏感(全本地链路)、终端原教旨主义者。
不适合谁:需要企业级 SLA 的团队、深度绑定某家 Agent 生态的用户、不想碰 dev 版本软件的稳健派。
七、总结:Harness 战争的下半场
jcode 最有价值的地方,不是某个具体功能,而是它验证了三个判断:
第一,Coding Agent 的竞争正在从「接哪个模型」转向「Harness 工程质量」。 模型能力日趋同质化(都能接,OAuth 一下的事),而 20 倍的内存差距、245 倍的启动差距、有无跨会话记忆——这些 Harness 层的差异是实打实的日常体验鸿沟。
第二,多 Agent 时代,资源效率就是架构能力。 「Agent 集群」概念喊了一年多,真正的拦路虎不是编排算法,而是每个 Agent 200MB+ 的物理成本。jcode 用 ~10MB 的边际会话成本证明:先把单体做轻,群体智能才有土壤。
第三,Agent 记忆不需要重型基建。 本地嵌入 + 图结构 + JSON 文件的组合,在个人开发场景下完胜「再买一个向量数据库」的方案。人类可读、可直接编辑的记忆存储,可能才是正确的默认形态。
一个人、一门语言、9.2 万行代码,把行业里所有「等模型更强了再说」的懒惰假设戳了个洞。下次当你的 Coding Agent 又在启动画面上转圈时,不妨想想:卡住你的到底是 AI,还是那 3.4 秒的 Node.js 冷启动?
项目地址:https://github.com/1jehuang/jcode (MIT 协议)