claw-code 的 Python 移植工作区 src/:镜像 TypeScript 源码与 parity 审计的完整指南
本文基于 src/AGENTS.md 展开,讲清 claw-code 仓库中 src/ 目录的定位、目录结构、CLI 子命令体系与 parity 审计机制。读完本文,你能够准确判断哪些模块属于「占位骨架」、哪些包含真实逻辑,能够用 python -m src.main 的各个子命令检查移植清单,并理解 parity_audit.py 中硬编码映射的维护约束。
一、定位:这是移植工作区,不是生产代码
src/AGENTS.md 在开篇就明确了 src/ 的性质:
This is a porting workspace, not production code. Nothing here is imported by, built with, or shipped in the Rust product (
rust/crates/). The Python tree exists solely to mirror and track parity against the Claude Code TypeScript source.
也就是说:
src/下的 Python 代码不被rust/crates/导入、构建或打包进任何 Rust 产物;- 这棵 Python 树的唯一目的,是**逐文件镜像并对齐(track parity)**Claude Code 的 TypeScript 源码,作为重写过程的跟踪脚手架(scaffold),而非实现目标本身。
这一点与仓库整体结构一致:真正可运行的产品逻辑位于 rust/crates/(api、runtime、tools、plugins 等 crate),而 src/ 是一个独立的、纯标准库的 Python 工作区。
二、目录结构:38 个顶层镜像文件 + 30 个占位包
原文档给出的结构图如下(保留原貌):
src/
├── main.py # argparse CLI entry point (summary, parity-audit, manifest, etc.)
├── ~38 top-level .py # mirror TS root files one-to-one
├── models.py # frozen dataclasses: Subsystem, PortingModule, PermissionDenial, ...
├── parity_audit.py # hard-coded TS→Python filename mapping (main.tsx→main.py, etc.)
├── port_manifest.py # builds a manifest of the src/ tree itself
├── reference_data/ # tracked JSON snapshots extracted from the TS archive
│ ├── archive_surface_snapshot.json
│ ├── tools_snapshot.json, commands_snapshot.json
│ └── subsystems/*.json (29 per-subsystem records)
└── ~30 subdirectories/ # PLACEHOLDER PACKAGES (assistant/, bootstrap/, voice/, vim/, ...)
└── each contains only __init__.py loading subsystems/<name>.json
实际目录与描述完全吻合:src/ 下约 40 个顶层 .py 文件,约 30 个子目录包;src/reference_data/subsystems/ 中确有 29 个子系统的 JSON 记录(assistant.json … voice.json),src/reference_data/archive_surface_snapshot.json 则记录了 TS 快照的根文件与根目录清单。
占位包遵循同一模板
所有占位子目录(voice/、vim/、assistant/、bootstrap/ 等)背后没有任何真实功能。以 src/voice/init.py 为例:
"""Python package placeholder for the archived `voice` subsystem."""
from __future__ import annotations
from src._archive_helper import load_archive_metadata
_SNAPSHOT = load_archive_metadata("voice")
ARCHIVE_NAME = _SNAPSHOT["archive_name"]
MODULE_COUNT = _SNAPSHOT["module_count"]
SAMPLE_FILES = tuple(_SNAPSHOT["sample_files"])
PORTING_NOTE = f"Python placeholder package for '{ARCHIVE_NAME}' with {MODULE_COUNT} archived module references."
它做的事只有两件事:通过共享助手 src/_archive_helper.py 的 load_archive_metadata() 读取 reference_data/subsystems/<name>.json,再重导出 ARCHIVE_NAME、MODULE_COUNT、SAMPLE_FILES、PORTING_NOTE 四个常量。load_archive_metadata() 的实现也很短——解析 reference_data/subsystems/{package_name}.json 并返回 dict(见 src/_archive_helper.py 的 load_archive_metadata 函数)。例如 voice 子系统的快照内容:
{
"archive_name": "voice",
"package_name": "voice",
"module_count": 1,
"sample_files": ["voice/voiceModeEnabled.ts"]
}
因此 from src import voice; voice.MODULE_COUNT 拿到的是归档元数据,不是可执行的语音代码。
三、CLI:python -m src.main 的子命令全景
Where to look 部分给出的“目标 → 起点”对照表值得完整保留:
| 目标 | 起点 |
|---|---|
| 理解 CLI 子命令 | main.py |
| 查看哪些 TS 文件映射到哪个 .py | parity_audit.py |
| 查找共享数据结构 | models.py |
| 检查 TS 归档元数据 | reference_data/ |
| 真实逻辑(权限、路径作用域) | permissions.py、path_scope.py |
| Query engine 垫片 | query_engine.py |
| 运行时模拟 | runtime.py |
| 测试 | 仓库根目录 tests/(test_porting_workspace.py、test_security_scope.py) |
运行测试:在仓库根目录执行 python -m unittest discover -s tests。
从 src/main.py 的 build_parser() 看,CLI 共注册了 21 个子命令,可归纳为四类:
1. 工作区报告类(直接打印 Markdown):
| 子命令 | 作用(main.py 中的 help 文案) |
|---|---|
summary |
渲染 Python 移植工作区的 Markdown 摘要 |
manifest |
打印当前 Python 工作区清单 |
parity-audit |
在本地 TS 归档可用时,与归档对比 parity |
setup-report |
渲染启动/预取 setup 报告 |
command-graph |
展示命令图分段 |
tool-pool |
展示默认配置下组装的工具池 |
bootstrap-graph |
展示镜像的 bootstrap/runtime 图阶段 |
2. 清单查询类(带筛选参数):
subsystems --limit N(默认 32):列出工作区中的 Python 模块;commands --limit N --query X --no-plugin-commands --no-skill-commands:列出归档快照中的命令条目;tools --limit N --query X --simple-mode --no-mcp --deny-tool T --deny-prefix P:列出工具条目,且支持通过ToolPermissionContext.from_iterables(args.deny_tool, args.deny_prefix)构造权限上下文(见 src/main.py 中tools分支),这也是tools子命令与真实权限模型(permissions.py)挂钩的地方。
3. 运行时模拟类:route、bootstrap、turn-loop、flush-transcript、load-session,以及 remote-mode / ssh-mode / teleport-mode / direct-connect-mode / deep-link-mode 五个「target 位置参数」的运行时分支模拟(见 src/main.py)。
4. 单条目查询与垫片执行类:show-command NAME、show-tool NAME、exec-command NAME PROMPT、exec-tool NAME PAYLOAD。
这里要特别强调一条约定:main.py 只是在镜像清单上模拟路由、turn-loop 与 bootstrap;只读垫片返回 handled/message 结果,它从不调用 LLM。例如 exec-command 打印 result.message 并以 0 if result.handled else 1 作为退出码(src/main.py)——它执行的是元数据垫片,而非真实命令。turn-loop 的 --max-turns 默认 3,--structured-output 打开结构化输出;QueryEnginePort 的配置默认值可在 src/query_engine.py 的 QueryEngineConfig 中看到:max_turns=8、max_budget_tokens=2000、compact_after_turns=12、structured_retry_limit=2。
四、parity_audit.py:硬编码的 TS→Python 映射与审计报告
parity_audit.py 是整个工作区对齐机制的核心,文档要求「不要让 parity_audit.py 漂移(drift):重命名镜像模块时必须同步更新其中的硬编码映射」。从源码看,映射由两张表构成:
根文件映射 ARCHIVE_ROOT_FILES(18 项,.ts/.tsx → .py):
ARCHIVE_ROOT_FILES = {
'QueryEngine.ts': 'QueryEngine.py',
'Task.ts': 'task.py',
'Tool.ts': 'Tool.py',
'commands.ts': 'commands.py',
...
'main.tsx': 'main.py',
'replLauncher.tsx': 'replLauncher.py',
'tools.ts': 'tools.py',
}
注意大小写与下划线并不机械转换:cost-tracker.ts → cost_tracker.py(连字符变下划线),而 costHook.ts → costHook.py、QueryEngine.ts → QueryEngine.py 保留了 camelCase 原名——这正是约定中提到的 camelCase 例外。
目录映射 ARCHIVE_DIR_MAPPINGS(35 项),把 TS 侧根目录一一对应到 Python 包或单文件,其中包含两处需要留意的转换:'native-ts': 'native_ts'(连字符目录转下划线)以及 'commands': 'commands.py'、'context': 'context.py'、'ink': 'ink.py'、'query': 'query.py'、'tasks': 'tasks.py'、'tools': 'tools.py' 这类「目录坍缩为单文件」的映射(src/parity_audit.py)。
审计结果封装在 frozen dataclass ParityAuditResult 中,字段包括 archive_present、root_file_coverage、directory_coverage、total_file_ratio、command_entry_ratio、tool_entry_ratio 以及两个缺失清单;其 to_markdown() 渲染成「Root file coverage: x/y」等行,归档不存在时则明确提示「Local archive unavailable; parity audit cannot compare against the original snapshot.」(src/parity_audit.py)。
测试侧对这一机制有硬性约束:tests/test_porting_workspace.py 的 test_root_file_coverage_is_complete_when_local_archive_exists 断言——当本地归档存在时,根文件覆盖必须 100%(root_file_coverage[0] == root_file_coverage[1]),目录覆盖 ≥ 28,命令条目 ≥ 150,工具条目 ≥ 100。test_subsystem_packages_expose_archive_metadata 则验证 assistant、bridge、utils 等占位包暴露的 MODULE_COUNT > 0(utils 甚至要求 > 100)。这些断言就是「映射不允许漂移」的可执行护栏。
五、共享数据结构:models.py 的 frozen dataclasses
约定要求 models.py 中的 dataclass 全部 frozen,渲染器统一采用 as_markdown() / to_markdown() 命名。对照 src/models.py 源码:
Subsystem(frozen):name、path、file_count、notes,是port_manifest.py中顶层模块条目的载体;PortingModule(frozen):name、responsibility、source_hint、status='planned'——source_hint字段正是「每个镜像条目都携带指回原.ts/.tsx路径的source_hint」这一约定的数据层实现,CLI 输出中- {module.name} — {module.source_hint}打印的就是它(src/main.py);PermissionDenial(frozen):tool_name、reason、status='blocked';UsageSummary(frozen):以词元数量近似统计 token,add_turn()返回新实例而非原地修改,符合 frozen 语义;PortingBacklog(可变):summary_lines()渲染为- {name} [{status}] — {responsibility} (from {source_hint})格式的 Markdown 行。
src/port_manifest.py 的 build_port_manifest() 递归统计 src/ 下全部 .py 文件,按顶层目录/文件名聚合成 Counter 并排序输出 PortManifest,其中对 main.py('CLI entrypoint')、models.py('shared dataclasses')等文件附带固定 notes。这也是 subsystems 与 manifest 两个子命令的数据源。
六、编码约定(完整继承)
以下约定原文列于 src/AGENTS.md 的 CONVENTIONS 一节,是修改本目录任何文件前必须遵守的规范:
- 文件名 snake_case,但保留 TS 原名;TS 原文件使用 camelCase 的保留 camelCase:
QueryEngine.py、costHook.py、replLauncher.py(对应parity_audit.py映射表中的同名条目)。 - 每个镜像条目都携带
source_hint,指回其原始.ts/.tsx路径。 - 全库
from __future__ import annotations;纯标准库,无第三方依赖。 models.py的 dataclass 为 frozen;渲染器命名为as_markdown()/to_markdown()。main.py只模拟:在镜像清单上跑路由、turn-loop、bootstrap;只读垫片返回 handled/message 结果,从不调用 LLM。- 薄垫片模块(如
ink.py)只是 backlog 元数据,不是可运行代码。
七、反模式(ANTI-PATTERNS):四条红线
原文档最后列出的四条「不要做」,是对维护者的硬性约束:
- 不要在这里添加真实的 agent、tool、voice 或 vim 功能。 那属于
rust/crates/。src/是脚手架,不是实现目标。 - 不要提交
archive/下的任何东西。 本地 TS 快照(archive/claude_code_ts_snapshot/src)被 gitignore;被跟踪的抽取物在reference_data/中,应基于后者工作。 - 不要让
parity_audit.py漂移。 重命名镜像模块时,必须同步更新其中的硬编码映射。 - 不要添加第三方依赖。 一切都跑在标准库上。
第 2 条与 parity_audit.py 中的 ARCHIVE_ROOT = .../archive/claude_code_ts_snapshot/src 路径定义相呼应:审计命令优雅降级——归档不在时输出「cannot compare」提示而非报错(ParityAuditResult.to_markdown() 首分支),使 parity-audit 在任何克隆环境下都能安全运行。
八、验证与继续深入
确认本工作区行为的最直接方式是运行测试:
# 仓库根目录
python -m unittest discover -s tests
相关测试文件:tests/test_porting_workspace.py(manifest 计数、CLI 子进程调用、parity 覆盖、占位包元数据)与 tests/test_security_scope.py。
进一步阅读建议按主题索引:
- 想弄清某个
.py对应哪个 TS 文件 → src/parity_audit.py; - 想看 TS 归档的根文件/根目录清单 → src/reference_data/archive_surface_snapshot.json;
- 想看命令/工具快照条目 → src/reference_data/commands_snapshot.json、src/reference_data/tools_snapshot.json;
- 想看真实逻辑(权限与路径作用域)→ src/permissions.py、src/path_scope.py,而非那些占位包;
- 想看真正的产品实现 → rust/crates/ 下各 crate。
一句话总结:src/ 是 claw-code 重写过程中的一棵「镜像骨架树」——约 38 个顶层 .py 一对一镜像 TS 根文件,约 30 个子目录包仅承载归档元数据,parity_audit.py 用两张硬编码映射表 + 覆盖率审计把「镜像是否漂移」变成可运行、可断言的问题;任何在此树内的改动都必须遵守纯标准库、frozen dataclass、camelCase 例外保留、映射同步这四类约束,而真实功能永远落在 rust/crates/ 一侧。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00