Loom
简体中文 | English
基于 AI 的 JSON Schema 文档生成器,集成 TUI 交互、Web 浏览器与 Mock 服务

✨ 特性
- 🤖 AI 驱动的 Schema 生成 —— 通过 TUI 聊天界面与大模型(DeepSeek、OpenAI)对话生成和更新 JSON Schema API 文档
- 🧩 实体(Entity)建模 —— 在
docs/entities 中维护可复用的实体 Schema,通过 x-entity-ref 在接口 Schema 中引用
- 📚 现代 Web 浏览器 —— 基于 React 的 SPA,用于浏览模块、接口和实体,支持交互式 Schema 渲染
- ⚡ Mock 服务 —— 基于 JSON Schema 动态生成贴近真实的 Mock 数据
- 🖥️ TUI 内服务控制 —— 直接在 TUI 中启动/停止/重启 Mock 与 Web Viewer(
/mock、/view)
- 🗂️ Manifest 索引 —— 内置
loom manifest rebuild 命令重建依赖/索引一致性
- ☁️ 在线发布 —— 支持外层
loom plans/purchase/publish,也支持 loom chat 内 /plans、/purchase、/publish
- ⬆️ 自动升级提示 —— 启动时检查 npm 上的新版本,确认后可自动升级
- 🔧 TypeScript 优先 —— 完整类型定义,现代化的 TypeScript 架构
📦 安装
环境要求
- Node.js ≥ 18.0.0
- npm 或 yarn
- DeepSeek API Key(必需)
全局安装
npm install -g @vegamo/loom
yarn global add @vegamo/loom
⚙️ 配置
配置文件
默认全局配置路径:
- macOS/Linux:
~/.loom/config.json
- Windows:
%APPDATA%/loom/config.json
首次运行 loom chat 时,会以交互向导的形式引导你创建/更新该全局配置文件。
聊天首次引导的默认值:
provider:deepseek
model:deepseek-chat
baseURL:https://api.deepseek.com/v1
apiKey:必填,需由用户输入
你也可以手动创建全局配置:
{
"outDir": "docs",
"llm": {
"provider": "deepseek",
"model": "deepseek-chat",
"baseURL": "https://api.deepseek.com/v1",
"apiKey": "your_deepseek_api_key",
"temperature": 0.7,
"maxTokens": 2000
},
"serve": {
"port": 3000,
"host": "0.0.0.0"
},
"mock": {
"port": 3001,
"host": "0.0.0.0"
}
}
docs/ 目录仍保留在各项目目录中(通过 --dir 指定),不会被移动到全局存储。
🚀 快速开始
1. 生成 API 文档
loom chat
loom chat --dir ./my-api-project
在 loom chat 中,你也可以控制本地服务:
/mock、/mock stop、/mock restart [port]
/view、/view stop、/view restart [port]
2. 浏览文档
loom view
loom view --port 8080
3. 启动 Mock 服务
loom mock
loom mock --port 8081
4. 组合服务(推荐)
loom serve
5. 发布到 Loom Server
loom plans
loom purchase basic_annual
loom publish
loom chat
/plans
/purchase basic_annual
/publish
首次执行 loom plans / loom purchase / loom publish,或在 TUI 内执行 /plans / /purchase / /publish 时,Loom 会自动生成并保存发布 token:
~/.loom/auth.json
默认发布服务地址是:
https://loom-server.vegamo.cn
这个地址内置在 Loom CLI 中;~/.loom/auth.json 只保存用户身份 token。
用户不需要手动执行 token 初始化命令。发布时,Loom 会在当前项目根目录写入项目级配置:
.loom/project.json
该文件保存稳定的 projectSlug、名称、描述和可见性。后续即使项目目录改名,loom publish 或 /publish 仍会继续发布到同一个服务端项目。
如果当前 token 没有 active pro,也没有可用 basic slot,loom publish 和 /publish 会停止上传并提示执行 loom plans / /plans 或购买命令。
6. 升级 Loom
loom upgrade
执行其它命令时,Loom 也会检查 npm 是否有新版本。
发现新版本时,确认即可自动升级。
📖 使用指南
loom chat
通过 AI 对话生成 JSON Schema 文档的交互式终端 UI。
loom chat [options]
Options:
-d, --dir <path> 目标项目目录(默认:当前目录)
-h, --help 显示帮助
典型流程:
- 运行
loom chat
- 用自然语言描述你的 API 接口
- AI 生成结构合理的 JSON Schema
- Schema 文件被保存到
docs/ 目录(可配置)
内置聊天命令:
- 输入提示:
Enter 发送,Shift+Enter/Alt+Enter 换行,↑/↓ 浏览历史记录(跨会话持久化),Tab 自动补全命令
/help —— 显示命令帮助
/reset —— 重置对话历史
/list —— 列出已生成的 Schema 文件
/mock、/mock stop、/mock restart [port] —— 管理 Mock 服务
/view、/view stop、/view restart [port] —— 管理 Web Viewer
/scan <dir> —— 通过 LLM 从源码中识别 API;/scan resume、/scan reset 管理断点
/abort —— 中止当前请求
/exit —— 退出 Loom
loom view
基于 React SPA 的现代化 Web 文档浏览器。
loom view [options]
Options:
-p, --port <number> 端口号(默认:3000)
-d, --dir <path> 目标项目目录(默认:当前目录)
-h, --help 显示帮助
特性:
- 📁 按模块浏览,显示接口数量
- 🧩 浏览
docs/entities 中的实体
- 🔍 在模块与接口范围内实时搜索
- 📊 类 Swagger 的 Schema 表格视图,覆盖所有请求/响应区段(query、path、headers、body)
- 🔗 渲染接口请求/响应时自动解析
x-entity-ref
- 🎨 简洁的响应式 UI,深色侧边栏
- 🔗 支持接口的直链访问
loom mock
基于 JSON Schema 动态生成数据的 Mock API 服务。
loom mock [options]
Options:
-p, --port <number> 端口号(默认:3001)
-d, --dir <path> 目标项目目录(默认:当前目录)
-h, --help 显示帮助
特性:
- 🚀 自动从 JSON Schema 文件注册路由
- 🎲 基于 mock-json-schema 智能生成 Mock 数据
- 📡 支持所有 HTTP 方法(GET、POST、PUT、DELETE、PATCH)
- 🔧 可配置响应状态码与 Schema
loom serve
组合服务,同时运行 Web Viewer 与 Mock 服务。
loom serve [options]
Options:
-p, --port <number> 端口号(默认:3000)
-d, --dir <path> 目标项目目录(默认:当前目录)
-h, --help 显示帮助
URL 结构:
http://localhost:3000/ —— Web 文档浏览器
http://localhost:3000/api/docs —— 文档 API
http://localhost:3000/api/schemas —— Schema 文件 API
http://localhost:3000/api/entities —— 实体文件 API
http://localhost:3000/mock/... —— Mock API 路由
发布命令
发布相关能力同时支持外层 CLI 和 loom chat 内斜杠命令。
loom plans / /plans
查看可购买套餐和当前发布权益。该命令会自动生成本地发布 token,并调用服务端查询当前 pro、slot 和项目状态。
loom plans
/plans
loom purchase / /purchase
为当前自动生成的发布 token 购买或续费套餐。
loom purchase <basic_annual|pro_annual>
/purchase <basic_annual|pro_annual>
命令会创建支付订单、在 TUI 中显示二维码,并在支付后轮询确认结果。支付成功后即可执行 loom publish 或 /publish。
loom publish / /publish
发布当前项目的 docs/ 文档包到 loom-server。项目不存在时,服务端会尝试创建项目;如果没有可用权益,命令会提示先购买。
loom publish
/publish
项目身份由当前 token 和 projectSlug 共同确定。CLI 会把项目级发布配置写入 .loom/project.json:
{
"projectSlug": "my-api",
"name": "My API",
"description": "",
"visibility": "public"
}
后续发布默认复用该文件中的 projectSlug;如需切换到新项目,需要调整 .loom/project.json 中的项目配置。
loom manifest rebuild
重建文档清单索引文件 .loom-manifest.json,确保依赖/索引一致。
loom manifest rebuild [options]
Options:
-d, --dir <path> 目标项目目录(默认:当前目录)
-h, --help 显示帮助
loom upgrade
将 loom 升级到 npm 上的最新版本。
loom upgrade
📝 JSON Schema 格式
Loom 使用一套为 API 文档优化的自定义 JSON Schema 格式:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Authentication API",
"description": "User authentication endpoints",
"version": "1.0.0",
"endpoints": [
{
"path": "/api/auth/login",
"method": "POST",
"summary": "User login",
"description": "Authenticate user with credentials",
"tags": ["auth"],
"request": {
"headers": {
"Content-Type": { "type": "string", "enum": ["application/json"] }
},
"body": {
"type": "object",
"properties": {
"username": { "type": "string" },
"password": { "type": "string" }
},
"required": ["username", "password"]
}
},
"response": {
"200": {
"type": "object",
"properties": {
"token": { "type": "string" },
"user": { "type": "object" }
}
},
"400": {
"type": "object",
"properties": {
"error": { "type": "string" }
}
}
}
}
]
}
Schema 结构说明
- title:API 模块标题
- description:模块描述
- endpoints:API 接口定义数组
- endpoint.path:URL 路径(支持路径参数)
- endpoint.method:HTTP 方法(GET、POST、PUT、DELETE、PATCH)
- endpoint.request:可选的请求 Schema(headers、params、query、body)
- endpoint.response:按状态码索引的响应 Schema
🧩 实体(Entity)Schema 与引用
Loom 支持以下位置的可复用实体 Schema:
docs/entities/*.entity.schema.json
实体文件示例:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "User",
"description": "Reusable user entity",
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"email": { "type": "string", "format": "email" }
},
"required": ["id", "name", "email"]
}
在接口 Schema 中通过 x-entity-ref 引用实体:
{
"user": {
"x-entity-ref": {
"entity": "User",
"pick": ["id", "name", "email"]
}
}
}
支持的形式:
- 字符串形式:
"x-entity-ref": "User"
- 对象形式:
"x-entity-ref": { "entity": "User", "pick": ["id", "name"] }
🏗️ 项目结构
loom/
├── src/
│ ├── agents/ # 支持工具调用的 AI Agent 系统
│ │ ├── core/ # Agent 核心逻辑
│ │ └── memory/ # 对话记忆管理
│ ├── llm/ # LLM 客户端(DeepSeek、OpenAI)
│ │ ├── client.ts # 流式 LLM 客户端
│ │ └── config.ts # LLM 配置
│ ├── tools/ # Agent 工具系统
│ │ ├── schema-gen.ts # Schema 生成工具
│ │ ├── schema-validate.ts # Schema 校验工具
│ │ ├── file-ops.ts # Schema 文件操作工具
│ │ ├── entity-file-ops.ts # 实体文件操作工具
│ │ └── entity-workflow.ts # 实体影响/同步/校验工具
│ ├── tui/ # 终端 UI(聊天界面)
│ │ ├── app.tsx # TUI 主应用
│ │ └── components/ # TUI 的 React 组件
│ ├── view/ # Web 文档浏览器
│ │ ├── server.ts # Fastify Web 服务
│ │ ├── routes/ # API 路由
│ │ ├── frontend/ # React SPA 前端
│ │ └── public/ # 静态资源
│ ├── mocks/ # Mock 服务
│ │ ├── server.ts # Mock 服务实现
│ │ ├── router.ts # 动态路由注册
│ │ └── generator.ts # Mock 数据生成
│ ├── shared/ # 共享工具
│ │ ├── config.ts # 配置加载器
│ │ ├── entity-utils.ts # 实体读写/引用工具
│ │ ├── manifest-utils.ts # 清单索引构建器
│ │ ├── schema-entity-resolver.ts # 给 Viewer API 用的 x-entity-ref 解析器
│ │ ├── types.ts # TypeScript 类型定义
│ │ └── logger.ts # 日志工具
│ ├── serve.ts # Viewer + Mock 组合服务
│ └── index.ts # CLI 入口
├── docs/ # 生成的 Schema 文件
├── scripts/ # 构建脚本
├── dist/ # 编译输出
└── package.json
🛠️ 开发
构建项目
npm run build
npm run build:view
npm run build:all
开发模式
npm run dev
npm run dev:view
添加新功能
- 新的 LLM 提供商:扩展
src/llm/config.ts 与 src/llm/client.ts
- 新的 Agent 工具:放在
src/tools/ 下,并在 src/agents/core/agent.ts 中注册
- UI 组件:放在
src/view/frontend/components/
- API 路由:放在
src/view/routes/ 或 src/mocks/router.ts
📦 发布到 npm
维护者发布新版本到 npm 的步骤:
npm login
npm version patch
npm run build:all
npm publish
npm publish --dry-run
包内容包括:
- 编译后的 JavaScript(
dist/)
- TypeScript 类型定义
- 预构建的 React 前端 Bundle
- CLI 可执行文件(
loom)
打包相关配置:
prepack 脚本确保打包前会重新构建
.npmignore 排除源码与开发期产物
- 运行时依赖均已正确声明
📋 更新日志
v0.4.0
- Added:新增
loom plans 和 TUI 内 /plans,同时展示可购买套餐和当前 token 的 pro/slot/项目状态
- Added:新增发布项目配置
.loom/project.json,loom publish / /publish 首次确定 projectSlug 后自动落盘,目录改名后仍发布到同一个项目
- Changed:移除用户侧
loom token / loom token show 流程;首次执行发布命令或埋点时自动生成 loom_live_ token 并保存到 ~/.loom/auth.json
- Changed:
loom publish / /publish 发布前检查权益;没有 active pro 或可用 basic slot 时停止上传并提示执行 plans / purchase
- Changed:静默埋点的
userToken 改为复用发布 token,方便关联使用、购买和发布行为
- Changed:
/scan 生成 endpoint response 时,不再把 CommonResult / Result / ApiResponse 等通用响应壳整体作为 response 引用,避免把真实 data payload 抹成泛型 object
- Changed:Phase 4(generate-endpoint)缓存键追加 prompt 语义版本;本次 response payload 规则升级后,重新扫描会跳过旧的 endpoint schema 缓存并重新生成
- Fixed:修复扫描结果页面中 response 的
data 字段显示不完整的问题;对于有实际返回体的接口,data 应生成具体 schema 或具体实体引用,无 payload 的成功响应则标记为可空/可选
v0.3.0
- Added:
/scan 与 /scan resume 新增 --lang zh|en 参数。Phase 3(generate-entity)和 Phase 4(generate-endpoint)按所选语言输出 description 与 summary 文本。默认 zh;可通过 ~/.loom/config.json 中的 scan.language 全局覆盖,或在执行命令时使用该参数
- Changed:
/scan 的 LLM 缓存对 Phase 3/4 改为按语言区分(键末尾追加 :zh 或 :en),Phase 1/2 仍跨语言共享。切换语言只会失效真正会变的那一半
- Changed:缓存的阶段标识符改名以匹配扫描流程的编号(
phase1 extract-endpoints、phase2 extract-entities、phase3 generate-entity、phase4 generate-endpoint)。升级自动迁移:旧版本的 Phase 1/2 记录继续命中;Phase 3/4 记录会在下次扫描时重新生成
- Removed:去掉全局
CACHE_VERSION 一刀切清空机制。缓存失效改由 source-hash + 每条记录的形状校验驱动。如有 prompt 重大变更,用户可手动 rm <outDir>/.loom-scan-cache.json 清空
- Fixed:Phase 4 当 LLM 漏掉
summary 时,不再回退到英文 brief,而是退化为 <METHOD> <path>,避免一句英文混在中文文档里
v0.2.0
- Added:
/scan <dir> —— 多语言、LLM 驱动的源码 API 识别。识别框架、用 glob 收紧文件范围、提取接口标识(Phase 1)、识别并生成实体 Schema(Phase 1.5),然后按路由前缀生成单文件 Schema(Phase 2,通过 x-entity-ref 引用实体)
- Added:
/scan resume 和 /scan reset —— 基于断点继续被中断的扫描,或丢弃已保存的断点
- Added:
/scan 的 LLM 输出缓存,按文件内容哈希索引(<outDir>/.loom-scan-cache.json);增量扫描会跳过未变更的文件,可节省 25 分钟以上。可使用 --no-cache 强制调用 LLM
- Added:
loom chat 的输入历史持久化在全局 ~/.loom/history.jsonl(上限 100 条),上下方向键跨会话浏览
- Added:斜杠命令 Tab 自动补全 —— bash 风格的公共前缀补全,候选列表内联展示
- Added:集中式的斜杠命令注册表(
src/tui/commands.ts),让 Header 面板、/help 文案与自动补全列表共享一份数据源
- Added:静默使用埋点 —— 每次 CLI 调用上报一次
{ userToken, action: "used" }。userToken 复用自动生成的发布 token,持久化于 ~/.loom/auth.json,离线时落到 ~/.loom/telemetry-outbox.jsonl
- Added:每次扫描的诊断日志
<outDir>/.loom-scan.log,以及来自 scan-failures.ts 的原始响应快照,便于排查 LLM 问题
- Improved:Phase 2 改为发送 handler 片段而非整文件,降低 token 消耗
- Improved:
/scan 容忍推理模型的输出格式(例如 DeepSeek-R1 在同一响应中先输出 <think> 再给出最终 JSON)
- Improved:LLM 客户端将
APIConnectionError 与 SDK 内部 abort 归为可重试的 timeout
- Fixed:对已经扫描完成的断点执行
/scan resume,现在会提示 "scan already complete" 而不是默默重跑 analyze
- Fixed:实体的可空性改用
required[] 表达,而不是 type 联合
- Fixed:在
doneCount 自增过程中保留 group 冲突策略
- Fixed:abort 时保留扫描子阶段,
/scan resume 能从正确步骤继续
- Fixed:聊天启动时的命令列表与
/help 同步(现在包含 /scan 与 /abort)
- Removed:禁用了
/init 命令;若项目里存在 requirement.md,仍会作为 agent 上下文加载
v0.1.6
- Added:每个接口都有 Mock view / Mock edit 页面,可从模块列表进入
- Added:手写的 Mock 响应以同名 sidecar 文件
<name>.mock.json 存储(每个接口同时只有一个生效 override)
- Added:Mock 服务会使用 override 的 HTTP 状态码响应(例如保存 400 的 mock 后,
/mock/<path> 会真的返回 HTTP 400)
- Added:Mock view/edit 中的状态码切换器,并标记哪些状态码已经存在 override
- Added:Mock view 提供 cURL 示例区块,基于接口的
request schema 生成(path、query、headers、body 全部填充示例值)
- Added:Mock body 内支持 Mock.js 表达式(
@cname、@integer(1,100)、'list|1-5': [...] 等)—— 模板原样存储,每次请求时再展开
- Removed:接口详情页内嵌的 "Mock Testing" 区块(已由独立的 Mock 页面替代)
v0.1.4
- Fixed:Web Viewer 中 GET 接口的 query 参数、path 参数和 headers 现在能正确显示
- Improved:所有请求/响应区段统一使用类 Swagger 的表格视图(SchemaTableViewer),含类型标签、约束、展开/折叠
- Fixed:启动 Web Viewer(
loom view)或组合服务(loom serve)时的 setNotFoundHandler 重复注册错误
- Removed:移除与 React 19 不兼容的
@stoplight/json-schema-viewer 依赖
🤝 贡献
欢迎贡献!流程如下:
- Fork 仓库
- 创建特性分支:
git checkout -b feature/amazing-feature
- 提交修改:
git commit -m 'Add amazing feature'
- 推送分支:
git push origin feature/amazing-feature
- 发起 Pull Request
开发准则
- 使用 TypeScript 严格模式
- 遵循既有代码风格与模式
- 为新功能补充测试
- 同步更新文档
📄 许可证
本项目采用 ISC 协议 —— 详见 LICENSE。
🙏 致谢
📞 支持
- Issues:GitHub Issues
- 文档:本 README 与代码注释
- 提问:欢迎在 Issues 或 Discussions 中提出
Made with ❤️ by the Loom team