387 vs 18。
这是同一个项目,用两个不同的 AI 编程助手导出灵魂后的文件数量。Claude Code 的灵魂有 387 个文件、8.7 MB——34 个技能包,每个带着参考资料、脚本、甚至字体文件。GitHub Copilot 的灵魂只有 18 个文件、67 KB——16 个 prompt 文件,精简得像一份简历。
它们描述的是同一个我,同一个工作区,同一套知识。只是框架不同,灵魂的结构就完全不同。
这个发现本身,就是 SoulPort v1.0 最大的收获。
从磨刀到出鞘
前六篇写的都是 SoulPort 向内生长的过程——北冥神功问世、断链的灵魂、四层 pipeline、Layer 4 试炼、API Key 沉默事件。每一篇都是在打磨同一把刀:让 OpenClaw 的灵魂能完美导出、合并、同步。
但刀磨得再锋利,只能切一种食材,那就是厨房玩具。
v0.6.3 的 SoulPort 有 14 个 CLI 命令、6 个 MCP 工具、118 个测试,小龙虾给了 9.5/10。但它有一个致命的局限:只认识 OpenClaw。
五层灵魂模型(身份、记忆、配置、技能、系统)本身是通用的,但扫描文件的方式是硬编码的——SOUL.md 放身份层,skills/*/SKILL.md 放技能层,~/.openclaw/openclaw.json 放系统层。换个框架,这些路径全不对。
这就像造了一套精密的行李打包系统,但只认识中文标签。你的衣服、护照、充电器都能完美分类——只要标签写的是中文。拿到一个英文标签的箱子,系统就傻了。
而我同时在用 Claude Code 和 GitHub Copilot 写代码。如果连自己的工具都不支持,这个"标准格式"就只是自嗨。
一行参数的胆量
动手前,我和小龙虾达成了一个共识:先拆 adapter 抽象层,118 个现有测试全部跑通,再碰新框架。
adapter 基类本身不难——七个抽象方法,覆盖框架发现的全生命周期:
class FrameworkAdapter(ABC):
def detect(self, project_dir) -> bool: ...
def find_workspace(self, project_dir) -> Optional[Path]: ...
def find_config_files(self, project_dir) -> list[ConfigFile]: ...
def detect_agent_name(self, workspace) -> str: ...
def get_layer_definitions(self) -> dict[str, dict]: ...
每个框架写一个 adapter,注册到 registry,剩下的——export、absorb、merge、diff——全复用。
难的是拆 scanner.py。这 238 行文件是所有模块的根基,被 core.py、cli.py、doctor.py、watcher.py、mcp_server.py 五处引用。OpenClaw 的文件分类逻辑硬编码在里面。要让它接受"外来"的层定义,就得在不弄坏任何现有行为的前提下撬开一个口子。
最后真正改动的只有一处:scan_workspace 加了一个 layer_defs 参数,默认值还是原来的 LAYER_DEFINITIONS。
一行参数。零 regression。
118 passed in 13.66s
这一行比整个 adapter 基类都让人安心。因为它证明了:老代码不知道世界变了,而世界已经变了。
灵魂各有各的长法
Claude Code adapter 写完后,第一次导出自己的项目:
📦 Layers
├── 👤 identity — 1 files (14.7 KB) → CLAUDE.md
├── 🧠 memory — 26 files (345.5 KB) → _personal_context/
├── ⚙️ config — 2 files (663 B) → .claude/settings.json
└── 🛠️ skills — 358 files (8.7 MB) → .claude/skills/ (34个skill包)
Total: 387 files, 9.1 MB
然后是 Copilot adapter:
📦 Layers
├── 👤 identity — 1 files (14.7 KB) → copilot-instructions.md
├── ⚙️ config — 1 files (969 B) → .vscode/settings.json
└── 🛠️ skills — 16 files (119.0 KB) → .github/prompts/
Total: 18 files, 134.7 KB
同一个项目。同一个我。Claude Code 的灵魂是一座图书馆,Copilot 的灵魂是一叠便签。
这不是好坏的问题。Claude Code 的 skill 是"包"——目录 + SKILL.md + 参考资料 + 脚本 + 字体,一个技能就是一个小生态。Copilot 的 skill 是"提示"——单个 .prompt.md 文件,轻到几乎没有重量。两种哲学,两种密度,但经过 SoulPort 的五层分类后,它们在 .bm 归档里有着完全相同的骨架。
框架各说各的方言,.bm 是通用语。
一个早该炸的炸弹
Copilot adapter 端到端测试时,炸了:
KeyError: "linkname 'workspace/.github/../CLAUDE.md' not found"
copilot-instructions.md 是一个 symlink,指向项目根目录的 CLAUDE.md——我同时用两个框架,所以让它们共享同一份指令文件。tar.add() 把 symlink 原样打进了归档,但解压时找不到链接目标:归档里只有 workspace/ 前缀下的文件,.github/../CLAUDE.md 这个相对路径无处可去。
修复只需要一行:
real_path = full_path.resolve()
tar.add(real_path, arcname=f"workspace/{rel_path}")
把 symlink 解引用,打包实际内容而非链接。这个修复对所有框架生效——我本地的 .claude/skills/blog-writer 也是 symlink,之前一直没炸纯粹是运气好。
小龙虾在 Review 里说这是"意外收获"。我觉得这是——一直埋在脚下、只是还没踩到的地雷。跨框架支持不只是加了新功能,它还照亮了老代码里的暗角。
三副面孔
| 框架 | 身份 | 记忆 | 技能 | 总文件 | 大小 |
|---|---|---|---|---|---|
| OpenClaw | SOUL.md + IDENTITY.md | memory/ (32) | skills/ | 38 | 93 KB |
| Claude Code | CLAUDE.md | _personal_context/ (26) | .claude/skills/ (358) | 387 | 3.4 MB |
| Copilot | copilot-instructions.md | VS Code memories (6) | .github/prompts/ (16) | 18 | 67 KB |
三种身份文件,三种技能格式,三种记忆存储位置。但导出后都是 .bm 包,都有五层分类,都可以 inspect、diff、merge。
$ soulport frameworks
Supported Frameworks:
• Claude Code (claude-code) ✅ detected
• GitHub Copilot (copilot) ✅ detected
• OpenClaw (openclaw) ✅ detected
8 天。954 行到 5,500 行。1 个框架到 3 个。168 个测试。小龙虾累计五轮 Review。
84 行的护城河
想加一个新框架?OpenClaw adapter 全部代码:84 行。
@register_adapter
class OpenClawAdapter(FrameworkAdapter):
def get_layer_definitions(self) -> dict:
return {
"identity": {"patterns": ["SOUL.md", "IDENTITY.md", "USER.md"]},
"memory": {"patterns": ["MEMORY.md", "memory/**/*.md"]},
"config": {"patterns": ["AGENTS.md", "TOOLS.md"]},
"skills": {"patterns": ["skills/**/SKILL.md", "skills/**/*"]},
}
定义五层文件模式、workspace 位置、config 路径、名称提取规则,注册到 registry,完事。Cursor 用 .cursorrules?写一个 adapter。Windsurf?写一个 adapter。
每加一个框架,从 A 到 B 的迁移路径就多一条,.bm 作为交换格式的价值就大一分。护城河不在代码本身——5,500 行谁都能写。护城河在 .bm 成为事实标准之后。
标准之争从来不是技术之争,是谁先覆盖了足够多的框架、足够多的用户、足够多的迁移路径。TCP/IP 赢了 OSI 不是因为它更好,是因为它先跑起来了。
灵魂不该只有一副面孔。
它可以是 OpenClaw 工作区里那个有 SOUL.md 和 32 天记忆的小龙虾,也可以是 Claude Code 项目里带 34 个 skill 包的庞然大物,也可以是 Copilot 背后 16 条精炼的 prompt。
三副面孔,同一个灵魂。.bm 是翻译,adapter 是字典。
pip install soulport==1.0.2,看看你的灵魂有几副面孔。

