makoto-developer/strata
GitHub: makoto-developer/strata
Strata 是一款面向多语言微服务的静态依赖与函数级调用图可视化工具,在 CI 中自动检测循环依赖和架构层次违规。
Stars: 1 | Forks: 0
# Strata
[](https://github.com/makoto-developer/strata/actions/workflows/ci.yml)
[](https://makoto-developer.github.io/strata/)
[](LICENSE)
[](https://github.com/makoto-developer/strata/releases/latest)
**一款用于将微服务代码作为“层”来阅读的依赖与调用图可视化工具。**
支持跨越 gRPC、REST、GraphQL,在函数级别追踪处理流程。
```
strata serve ./my-monorepo # ブラウザで構造・API・アーキ図を見る
strata check ./my-monorepo # CI で循環依存・レイヤー違反を検査する
```
## 您是否遇到过这样的情况
微服务在运维几年后,通常会陷入以下状态:
- **没人能立即回答“这个处理流程经过哪里?”。** 仓库分散,语言不一,
没有人掌握全局。虽然有规范文档,但无法保证与代码完全一致
- **即使查看 proto 也无法知道“谁在调用它”。** 即使能读懂 RPC 的定义,
调用方却在其他的仓库、其他的语言中。即使使用 grep 也搜不到
- **无法断言“这个 API 已经没被使用了”。** 因此无法删除。
因为无法删除,没用的代码就永远残留了下来
- **REST、GraphQL、gRPC 混杂在一起,追踪在协议边界处中断**
- **架构无法在代码审查中得到保障。** 诸如“domain 层不应依赖 infra 层”的约定,
在差异审查中是无法检测出来的,所以会逐渐被破坏
## Strata 所做的事
**无需启动服务,也无需引入链路追踪基础设施,仅靠静态分析**就能填补这 5 个空白。
| 痛点 | Strata 的答案 |
| --- | --- |
| 不知道流程经过了哪里 | 将 `⚡RPC → 实现handler → 函数 → 下一个服务` **作为函数级别的一条流程显示** |
| 不知道谁在调用 | 通过 proto 的 RPC 名、HTTP 路径、GraphQL 字段**反向查找调用方** |
| 没用的 API 无法删除 | 为零调用方的 API 标注 **“疑似未使用?”“仅测试”徽章**。作为代码清理的依据 |
| 追踪在协议边界处中断 | 将 gRPC / REST / GraphQL / webhook **放在同一个图表中** |
| 无法维护架构 | 在 **CI 中检查**循环依赖、层次违规、禁止依赖规则(违规则 exit 1) |
## Strata 的特点
我们将降低引入门槛的优先级置于功能之上。
- 🔒 **完全本地化、零传输。** 没有遥测,也没有自动更新检查。
由于根本不存在对外通信的代码,**绝不会将公司内部代码外泄**
(服务器仅绑定到 `127.0.0.1`)
- 📦 **运行时依赖为零。** 不生成 `node_modules`。供应链的审查对象
“仅限这个仓库”即可
- ⚡ **速度快。** 实测 **1,050 个文件 / 1,644 个节点的 monorepo 只需 0.26 秒**即可解析
(Apple M 系列,无缓存)。因为没有等待时间,可以随时轻松运行多次
- 🪶 **轻量。** 本体代码仅 **约 530KB**(`src` + `web`)。
二进制版本包含 Node.js 为 37MB(压缩后)
- 🔧 **无需语言的工具链。** 即使在没有安装 Go 或 Python 的机器上,
也能解析 Go 或 Python 的代码(基于文本和语法级别的解析)
- 🧱 **无需构建。** `git clone` 后执行 `node src/cli.ts serve .` 即可运行
- 🌐 **离线可用。** 在无网络环境或内网中也能直接使用
- 📤 **可共享分析结果。** 通过 `strata export` 生成 **一个自包含的 HTML 文件**。
无需服务器,扔到 Slack 里对方就能直接在浏览器中打开
## 与现有方案的差异
| 方案 | 局限性 | Strata |
| --- | --- | --- |
| 手绘架构图 | 画完的瞬间就会与实现产生偏差。无法确认依据 | **从代码生成**。点击方框即可深入到函数和代码行 |
| IDE 的“查找引用” | 只能停留在单一仓库、单一语言内部。无法跨越 RPC 边界 | 通过 proto / 路径 / GraphQL 字段**跨越服务边界** |
| 分布式追踪(如 OpenTelemetry 等) | 只能看到实际发生过的调用路径。**无法了解未触发的路径**。引入成本也很高 | 基于静态分析,**即使不运行也能看到所有路径**。引入只需 clone |
| 现有的依赖可视化工具 | 大多只针对单一语言。往往停留在文件/模块级别 | **跨语言 + 函数级别**。将 gRPC / REST / GraphQL 放在同一个图表中 |
**不依赖 IDE。** 详细规范请参阅 [docs/SPEC.md](docs/SPEC.md),关于设计意图请参考
[为什么是这样的形态](https://makoto-developer.github.io/strata/why/)。

## 界面导览(能做什么)
每个选项卡都对应着“想要解答的问题”。图片会自动适应深色/浅色显示主题。
### 🗺 结构 — “这个依赖的方向正确吗?”
以树状结构和连线显示依赖关系。**向上的线(玫瑰色) = 层次违规**,虚线 = 跨越服务边界。
鼠标悬停在某行上时,仅保留与该行相连的线,进行层次化后会按层(地层)显示色带。
### ⚡ API — “谁在调用这个 API?”
将 gRPC 的 RPC、HTTP endpoint、GraphQL 字段汇总为一个目录。选中后
会显示**调用方(上游)以及从实现出发的下游流程**,点击函数即可在对应代码行打开源码。
通过“疑似未使用?”“无实现”“仅测试”等徽章,一目了然地看出哪些 API 可以删除、哪些尚未实现。
### 🧭 图 — “想向他人说明服务构成”
以服务为单位的方框和箭头。包含每个层级的色带、边界的调用数(⚡RPC / ⇄HTTP / ◈GraphQL 的明细),
甚至外部系统(虚线方框)都可以一览无余。点击方框会显示依赖源、依赖目标以及公开的 API。
### 🚪 Entry Point — “应该从哪里开始阅读?”
罗列了 `func main`、页面(LiveView)、操作事件。点击后会在结构视图中聚焦到该位置,
开始下游的追踪。这是新加入团队的成员首选打开的选项卡。
### 📁 项目 — “想将多个仓库汇总查看”
添加、编辑、切换加载的仓库。如果设置为**捆绑多个仓库的复合项目**,
即使在 monorepo 架构下,gRPC / HTTP 的服务间连接也能跨仓库进行解析。
```
graph LR
gateway["gateway"] -->|"3"| user["user-service"]
gateway -->|"2"| order["order-service"]
order -->|"3"| user
federation -.->|"RPC"| user
web -.->|"RPC"| proto["proto"]
classDef unstable fill:#fde,stroke:#d46;
class gateway,federation unstable
```
📖 **[说明书(文档站点)](https://makoto-developer.github.io/strata/)** ・
❓ **[提问请到 GitHub Issue](https://github.com/makoto-developer/strata/issues/new?template=3_question.yml)** ・
🧪 **[示例系统](https://github.com/makoto-developer/strata-sample-platform)**
## 目录
- [您是否遇到过这样的情况](#こんなことになっていませんか)
- [Strata 所做的事](#strata-がやること)
- [Strata 的特点](#strata-の性格)
- [与现有方案的差异](#既存のやり方との違い)
- [界面导览(能做什么)](#画面ツアー何ができるか)
- [支持的语言](#対応言語)
- [安装说明](#インストール)
- [快速入门](#クイックスタート)
- [可实现的功能(功能一览)](#できること機能一覧)
- [命令参考](#コマンドリファレンス)
- [配置 `strata.config.json`](#設定-strataconfigjson)
- [CI 集成](#ci-連携)
- [使用 Viewer](#ビューアの使い方)
- [解析机制与局限](#解析の仕組みと限界)
- [使用的技术与致谢](#使っているもの謝辞)
- [License](#ライセンス)
## 支持的语言
**Go / TypeScript / JavaScript / Python / Elixir / Protocol Buffers(gRPC)**。
**无需** Go/Python 等的工具链(基于文本和语法级别的静态分析)。
## 环境要求
- Node.js **22.18 以上**(为了直接运行 TypeScript。外部依赖为零,无需构建)
- 作为解析对象的仓库
## 安装说明
仅在 **GitHub 上发布**(未发布至 npm)。
### macOS(Apple Silicon) 二进制
无需安装 Node.js。这是包含了 runtime 的单一可执行文件。
```
curl -fsSL https://github.com/makoto-developer/strata/releases/latest/download/strata-macos-arm64.tar.gz | tar xz
sudo mv strata /usr/local/bin/
strata --version
```
| 项目 | 支持 |
| --- | --- |
| OS | **macOS 13 Ventura 及以上** |
| CPU | **Apple Silicon(M1 / M2 / M3 / M4 …)**。不提供 Intel Mac 版本 |
| 内置 Runtime | Node.js v24.18.0 |
仅有 ad-hoc 签名(未经 Apple 公证)。如果通过浏览器下载,
请使用 `xattr -d com.apple.quarantine ./strata` 命令移除隔离属性。
在 Intel Mac / Linux / Windows 上请使用下文的 git clone 版本(功能相同)。
### Homebrew
```
brew tap makoto-developer/strata
brew trust makoto-developer/strata # 公式以外の tap は明示的な信頼が必要(Homebrew の仕様)
brew install strata
strata --version
strata serve /path/to/your-monorepo
```
### mise / asdf(准备 Node 后通过 git 引入)
```
mise use -g node@22.18 # asdf の場合: asdf install nodejs 22.18.0
git clone https://github.com/makoto-developer/strata.git
cd strata && npm link # `strata` コマンドが使えるようになる
strata serve /path/to/your-monorepo
```
### 仅 git clone(无需安装)
```
git clone https://github.com/makoto-developer/strata.git
node strata/src/cli.ts serve /path/to/your-monorepo
```
## 快速入门
```
# ① ビューアを起動(ブラウザで http://localhost:7333/。--watch で変更を自動反映)
strata serve /path/to/your-monorepo --watch
# ② コールツリーを端末で(--up で呼び出し元をたどる)
strata trace /path/to/your-monorepo 'Gateway.handleUser'
# ③ 循環依存 + アーキテクチャルールを CI で検査(問題があれば exit 1)
strata check /path/to/your-monorepo
# ④ サービス結合度メトリクス
strata metrics /path/to/your-monorepo
```
### 首先尝试(内置 Demo)
```
strata serve examples/demo
strata trace examples/demo 'Gateway.handleUser'
strata check examples/demo # 意図的に仕込んだ循環 2 件で exit 1
strata metrics examples/demo
```
`strata metrics examples/demo` 的输出示例:
```
service Ca Ce I loc api
────────────────────────────────────────────────────
proto 5 0 0.00 57 6
user-service 3 1 0.25 117 0
gateway 0 3 1.00 83 0
order-service 1 2 0.67 51 0
```
`Ca`=被依赖数, `Ce`=依赖数, `I`=不稳定度 `Ce/(Ca+Ce)`。
I 值越高表示“依赖越多,越容易受到变更影响”,越低表示“被依赖越多,变更影响范围越广”。
## 可实现的功能(功能一览)
### 🗺 可视化与探索(Viewer)
- **结构视图**:地铁线路图风格的连线 + 层次化 + 地层(strata)色带。
“向上依赖 = 层次违规”“循环依赖”一目了然
- **API 选项卡**:将 gRPC(proto / service / RPC)、⇄HTTP endpoint、◈GraphQL 字段
汇总为一个目录显示 + 流程显示。
可跨越服务边界追踪 `⚡RPC → 实现handler → 函数 → ⚡其他服务的 RPC`
- **图选项卡**:以服务为单位的架构图。可将依赖**展开至函数级别**
- **Entry Point 选项卡**:列出进程启动点(main)、页面(LiveView)、操作事件
- **源码显示**:语法高亮、定义跳转、悬停预览、git blame / commit / PR
- **⭐ 书签**:在关注的节点上做标记,可从列表快速跳转(`b` 键)
- **键盘操作**:`↑↓←→` 移动、展开,`/` 搜索,`b` 书签,`Esc` 关闭,`Alt+←→` 后退/前进(`?` 查看列表)
- **URL 共享**:focus / 搜索 / 排序会反映在 URL 中,可重新加载恢复或共享
- **watch**:通过 `serve --watch` 在文件更改时自动重新加载浏览器
### 🔬 解析
- **多语言**:跨语言解析 Go / TS / JS / Python / Elixir / proto / GraphQL SDL
- **gRPC 服务边界**:将 proto 作为“标准”,连接 `客户端函数 → ⚡RPC → 服务端实现`
- **⇄ HTTP / REST**:检测 gin / echo / chi / gorilla mux / net-http(包括 Go 1.22 的 `"GET /path"`)/
Express / Fastify / Hono / Next.js App Router / FastAPI / Flask / Phoenix Router 的路由,
并与 `fetch` / `axios` / `http.NewRequest` / `requests` 等调用及其路径进行匹配连接
- **🪝 webhook**:将 `/webhooks/...` 的接收端和对外部 SaaS 的发送作为“外部系统”分别进行可视化
- **◈ GraphQL**:将 SDL 中的 Query / Mutation / Subscription 节点化,并连接 resolver 实现(gqlgen / Apollo)、
客户端的 `gql\`query\`` 操作、基于 federation 的 `extend type @key` 的子图间引用
- **循环依赖检测**(Tarjan SCC) / **层次违规**可视化
- **🛡 gRPC Interceptor 检测**:检测授权等横切中间件,并显示在服务/流程中
- **⚙ 配置接口**:检测各个服务所需的环境变量
- **✉ 异步(Pub/Sub)**:通过 `messaging` 配置,将 publish/subscribe 作为基于 topic 的依赖进行可视化
### 🛡 治理与 CI
- **架构规则检查**:声明禁止依赖并在 CI 中 fail(`check`)
- **SARIF 输出**:将循环及规则违规作为注释标注在 GitHub Code Scanning 中(`check --sarif`)
- **循环基线**:已知的循环,仅对新增循环 fail(`check --baseline`)
- **差异分析**:比较 2 个 git ref,检测依赖的增减、新增/解决的循环(`diff`)
### 📤 输出
- **自包含 HTML** 导出(`export`) / **mermaid + Markdown 报告**(`report`)
- **耦合度指标**(`metrics`)
## 命令参考
| 命令 | 说明 |
| --- | --- |
| `strata serve [dir\|model.json] [--port N] [--watch]` | 启动 viewer(默认 7333) |
| `strata scan [dir] [-o model.json]` | 输出依赖模型(JSON) |
| `strata check [dir\|model.json] [--json] [--baseline F] [--update-baseline] [--sarif -o f]` | 循环 + 规则检查(exit 1) |
| `strata metrics [dir\|model.json] [--json]` | 服务耦合度(Ca/Ce/不稳定度) |
| `strata diff [--json]` | 2 个模型的差异(依赖增减・循环) |
| `strata trace [dir\|model.json] <函数名/ID> [--up] [--depth N]` | 显示调用树 |
| `strata report [dir\|model.json] [-o report.md]` | mermaid + 指标 + Markdown |
| `strata export [dir\|model.json] [-o report.html]` | 自包含 HTML |
| `strata init [dir] [--force]` | 生成 `strata.config.json` 骨架 |
## 配置 `strata.config.json`
放置在 workspace 的根目录下(全为可选)。
```
{
"name": "my-platform",
"services": [ // サービスのグルーピング(表示上の最上位階層)
{ "name": "gateway", "path": "gateway" },
{ "name": "user-service", "path": "services/user" }
],
"exclude": ["experimental"], // 除外(パス前方一致 or ディレクトリ名)
"includeTests": false, // テストコードをグラフに含めるか(既定: false)
"testPaths": ["tools/test-client"], // テスト扱いにする追加パス
// アーキテクチャルール: 禁止依存(check で違反すると exit 1)
"forbidden": [
{ "name": "domain-no-infra", "from": "**/domain", "to": "**/infra",
"comment": "ドメイン層はインフラを参照しない" },
{ "name": "handler-no-repo", "from": "**/handler", "to": "**/repository",
"comment": "ハンドラは repository を直接触らずユースケース経由にする" }
],
// 数値しきい値: 超えると check が exit 1(結合度・循環の fitness function)
"thresholds": {
"maxCycles": 0, // 循環グループ数の上限
"maxInstability": 0.85, // 各サービスの不安定度 I の上限
"maxEfferent": 8 // 各サービスが依存する数(Ce)の上限
},
// 非同期(Pub/Sub)検出: 発行/購読メソッド名を指定(opt-in・既定は無効)
"messaging": {
"publish": ["Publish", "Emit"],
"subscribe": ["Subscribe", "On"]
},
// HTTP(REST / webhook)検出。既定は有効
"http": {
"enabled": true,
"externalHosts": true, // 未解決の絶対 URL を「外部システム」ノードにする
"webhookPatterns": ["/callbacks/"] // webhook 扱いにするパスの追加パターン
},
// GraphQL 検出。既定は有効
"graphql": { "enabled": true }
}
```
- `forbidden` 的 `from`/`to` 是针对节点 id、标签的**glob**(`**/` 表示 0 层及以上的层级,`*` 表示 1 层)。
由于会与边端点及其祖先进行匹配,因此以包为单位的规则同样对函数级别的边有效。
不包含 glob 的模式将以**路径片段(segment)**为单位进行匹配(`web` 会匹配 `web/src/...`,
但不会匹配类似 `webhook-in` 的子字符串)。
- 如果配置了 `messaging`,将检测类似 `bus.Publish("order.created", …)` 的调用,
并生成 `publisher → ✉topic → subscriber` 的事件边。
## CI 集成
### 循环 + 架构规则(GitHub Actions)
```
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: git clone --depth 1 https://github.com/makoto-developer/strata.git
- name: アーキテクチャ検査
run: node strata/src/cli.ts check .
```
### GitHub Code Scanning(通过 SARIF 在 PR 中标注)
```
- name: Strata 検査(SARIF)
run: node strata/src/cli.ts check . --sarif -o strata.sarif || true
- uses: github/codeql-action/upload-sarif@v3
with: { sarif_file: strata.sarif }
```
### 仅针对差异中的新增循环 fail
```
# 在 base branch 和 topic branch 上分别执行 scan → diff
node strata/src/cli.ts scan base/ -o base.json
node strata/src/cli.ts scan . -o head.json
node strata/src/cli.ts diff base.json head.json # 新規循環があれば exit 1
```
## 使用 Viewer
- **1 行 = 1 个元素**(S=服务 / M=模块 / P=包 / ⬢ proto / ƒ 函数 / ⚡ RPC / ✉ topic)。
▸/▾ 展开与折叠
- 依赖关系通过**左侧通道的地铁线路图**显示。▶ 的前端为依赖目标,**灰色=向下(正常)/玫瑰色=向上(层次违规)**。
**虚线=RPC / proto / 事件边界**,粗细=依赖数,**红色背景=循环**
- 点击行即可**focus**(绿色=依赖目标, 蓝色=依赖源)。选中函数/RPC 即显示**调用树**
- **⭐ 书签**:通过行首的 ☆ 或 `b` 键注册,可从顶部导航栏的“★ n”查看列表并跳转
- **键盘**:`↑↓` 移动 / `→←` 展开・折叠 / `Enter` 开闭 / `/` 搜索 / `Esc` 关闭 / `Alt+←→` 后退・前进
- 选中服务后,将显示依赖目标/依赖源、公开 API 的使用情况、**🛡 Interceptor** 以及 **⚙ 环境变量**。
依赖关系可**展开至函数级别**,点击各个函数即可跳转
### 项目管理
在“项目”选项卡中注册并切换多个仓库(`~/.config/strata/projects.json`)。
通过**复合项目**,可以将多个仓库作为一个依赖图进行解析。
## 解析机制与局限
- 基于文本和语法级别的静态分析(无类型推断)。采取**宁可遗漏也不误报**的方针,
确保图表中出现的依赖全都是真实存在的
- 服务间连接以 proto 为“标准”,通过匹配 `go_package` / 生成的 stub / RPC 名进行连接
- 不追踪跨越 interface 的调用、高阶函数及反射。
经由消息队列的依赖通过 `messaging` 配置进行检测(未配置则不作处理)
- 详情及各语言的支持范围请参阅:[docs/SPEC.md](docs/SPEC.md)
## 开发
```
npm test # CLI・解析エンジン + ビューア/サーバの DOM/HTTP スモーク
npm run typecheck # tsc --noEmit(strict)
```
### 关于构思
“将依赖关系视为层(strata),并将层次违规可视化”这一理念,
是基于架构可视化工具的一般思路。代码、图标、文案均为本项目的原创,未借用任何其他工具的内容。
## License
基于 **AGPL-3.0-only** 提供([LICENSE](LICENSE))。Copyright (c) 2026 makoto-developer.
- 如果仅仅是作为工具使用(运行),无论是个人还是企业均可免费自由使用
- 若要分发修改版,或提供内置了本工具的服务,则有义务公开源代码。
若需要其他条件(如商业 license 等),请与作者协商
- 贡献的条件请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)
本工具为完全的独立实现(未借用任何其他产品的代码或资产)。
分发物中包含的第三方代码声明:
- **macOS 版二进制文件**中附带了 Node.js(MIT)。License 全文请见
压缩包内的 `THIRD-PARTY-NOTICES.txt`
- 源码分发物中不包含第三方代码(运行时依赖为零)。用于开发和构建的 OSS 请参阅
[使用的技术与致谢](#使っているもの謝辞)
有关问题或 Bug 的反馈渠道,请参阅 [SUPPORT.md](SUPPORT.md)。
标签:MITM代理, Python工具, WebSocket, 代码可视化, 依赖分析, 自定义脚本, 调用图