マイクロサービスのコードを「層」として読むための、依存関係とコールグラフの可視化ツール。 gRPC・REST・GraphQL をまたいで、関数レベルで処理を追えます。
strata serve ./my-monorepo # ブラウザで構造・API・アーキ図を見る
strata check ./my-monorepo # CI で循環依存・レイヤー違反を検査する📖 使い方の説明書 → https://makoto-developer.github.io/strata/
インストール手順・各画面の見方・設定リファレンス・CI への組み込み方・ 「なぜこの設計なのか」まで、まとまった説明書があります。 この README は概要です。実際に使うときはドキュメントサイトを見てください。
- ボタンと操作の一覧(画像つき)
- 構造ビューの読み方(線の色・向き・バッジ)
- API タブの読み方(未使用 API の判断・フローの読み方)
マイクロサービスを何年か運用すると、たいてい次の状態になります。
- 「この処理、どこ通ってる?」に誰も即答できない。 リポジトリが分かれ、言語も分かれ、 全体像を持っている人がいない。仕様書はあるが、コードと合っている保証がない
- proto を見ても「誰が呼んでいるか」が分からない。 RPC の定義は読めても、 呼び出し元は別リポジトリ・別言語のどこかにある。grep しても当たらない
- 「この API はもう使われていない」と言い切れない。 だから消せない。 消せないから、使われていないコードが永久に残る
- REST・GraphQL・gRPC が混在していて、追跡がプロトコルの境目で途切れる
- アーキテクチャがレビューで守れない。 「domain 層は infra を見ない」という決めごとは、 差分レビューでは検出できないので、じわじわ崩れる
サービスを起動せず、トレース基盤も入れず、静的解析だけでこの 5 つを埋めます。
| 困りごと | Strata の答え |
|---|---|
| どこを通っているか分からない | ⚡RPC → 実装ハンドラ → 関数 → 次のサービス を関数レベルで一本のフローとして表示 |
| 誰が呼んでいるか分からない | proto の RPC 名・HTTP のパス・GraphQL のフィールドで呼び出し元を逆引き |
| 使われていない API が消せない | 呼び出し元ゼロの API に 「未使用?」「テストのみ」バッジ。棚卸しの根拠になる |
| プロトコルの境目で追跡が切れる | gRPC / REST / GraphQL / webhook を同じグラフに載せる |
| アーキテクチャが守れない | 循環依存・レイヤー違反・禁止依存ルールを CI で検査(違反で exit 1) |
導入のハードルを下げることを、機能より優先しています。
- 🔒 完全ローカル・送信ゼロ。 テレメトリも自動アップデートチェックもありません。
外部への通信コードが存在しないので、社内のコードを外に出しません
(サーバーは
127.0.0.1にのみバインドします) - 📦 実行時依存ゼロ。
node_modulesを作りません。サプライチェーンの審査対象が 「このリポジトリだけ」で済みます - ⚡ 速い。 実測で 1,050 ファイル / 1,644 ノードのモノレポを 0.26 秒で解析 (Apple M シリーズ、キャッシュなし)。待ち時間がないので気軽に何度でも回せます
- 🪶 軽い。 本体のコードは 約 530KB(
src+web)。 バイナリ版は Node.js 同梱で 37MB(圧縮) - 🔧 言語のツールチェーンが要らない。 Go や Python を入れていないマシンでも、 Go や Python のコードを解析できます(テキスト・構文レベルの解析)
- 🧱 ビルド不要。
git cloneしてnode src/cli.ts serve .で動きます - 🌐 オフラインで完結。 ネットワークが無い環境・閉域網でもそのまま使えます
- 📤 成果物を共有できる。
strata exportで 1 枚の自己完結 HTML。 サーバー不要で、Slack に投げれば相手のブラウザでそのまま開けます
| やり方 | 限界 | Strata |
|---|---|---|
| 手描きのアーキテクチャ図 | 描いた瞬間から実装とずれる。根拠を確認できない | コードから生成。箱をクリックすれば関数と行まで降りられる |
| IDE の「参照を検索」 | 1 リポジトリ・1 言語の中で止まる。RPC の向こう側へ行けない | proto / パス / GraphQL フィールドでサービス境界を越える |
| 分散トレーシング(OpenTelemetry 等) | 実際に流れた経路しか見えない。動かしていない経路は分からない。導入コストも高い | 静的解析なので実行しなくても全経路が見える。導入は clone だけ |
| 既存の依存可視化ツール | 多くは 1 言語向け。ファイル/モジュール単位で止まることが多い | 多言語横断 + 関数レベル。gRPC / REST / GraphQL を同じグラフに載せる |
IDE 非依存。 詳細仕様は docs/SPEC.md、設計の意図は なぜこの形なのか を参照してください。
上のデモは
strata serve examples/demoの操作を録画したものです (再生成:scripts/record-demo.mjs)。
各タブは「答えたい問い」ごとに分かれています。画像はダーク / ライトの表示テーマに自動で追従します。
ツリー + 配線で依存を表示します。上向きの線(ローズ) = レイヤー違反、破線 = サービス境界越え。 行にホバーするとその行に繋がる線だけが残り、レベル化すると層(地層)ごとに帯が敷かれます。
gRPC の RPC・HTTP エンドポイント・GraphQL フィールドを 1 つのカタログに。選ぶと 呼び出し元(上流)と実装からの下流フローが出て、関数をクリックすればソースがその行で開きます。 「未使用?」「実装なし」「テストのみ」のバッジで、消せる API・未実装の API が一目で分かります。
サービス単位の箱と矢印。層ごとの帯、境界の呼び出し数(⚡RPC / ⇄HTTP / ◈GraphQL の内訳)、 外部システム(破線の箱)まで含めて俯瞰できます。箱をクリックすると依存元・依存先・公開 API が出ます。
func main・画面(LiveView)・操作イベントの一覧。クリックすると構造ビューでその位置にフォーカスし、
下流のトレースが始まります。新しくチームに入った人が最初に開くタブです。
読み込むリポジトリの追加・編集・切り替え。複数リポジトリを束ねた複合プロジェクトにすると、 マルチリポ構成でも gRPC / HTTP のサービス間接続がリポジトリを跨いで解決されます。
画像は
strata serve examples/demoの実画面です (再生成:scripts/capture-readme-shots.mjs)。 ビューア右上の ◐ ボタンで 自動 / ライト / ダークを切り替えられます。
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
📖 説明書(ドキュメントサイト) ・ ❓ 質問は GitHub Issue へ ・ 🧪 サンプルシステム
- こんなことになっていませんか
- Strata がやること
- Strata の性格
- 既存のやり方との違い
- 画面ツアー(何ができるか)
- 対応言語
- インストール
- クイックスタート
- できること(機能一覧)
- コマンドリファレンス
- 設定
strata.config.json - CI 連携
- ビューアの使い方
- 解析の仕組みと限界
- 使っているもの・謝辞
- ライセンス
Go / TypeScript / JavaScript / Python / Elixir / Protocol Buffers(gRPC)。 Go/Python 等のツールチェーンは不要(テキスト・構文レベルの静的解析)。
- Node.js 22.18 以上(TypeScript を直接実行するため。外部依存ゼロ・ビルド不要)
- 解析対象のリポジトリ
配布は GitHub 公開のみ(npm には公開していません)。
curl -fsSL https://raw.githubusercontent.com/makoto-developer/strata/main/install.sh | bashこれだけで /Applications/Strata.app に入ります。あとは Launchpad や Finder から
ダブルクリックするだけです。インストーラは dmg を取得してチェックサムを照合し、
配置したうえで隔離属性を外します(中身はこちら)。
ダブルクリックすると:
- 初回はフォルダ選択が出るので、解析したいリポジトリを選ぶ(2 回目以降は前回のフォルダで起動)
- ビューアが既定のブラウザで開く
- 小さなウィンドウが残るので、終わるときは「終了」を押す(サーバも一緒に止まります)
別のリポジトリに切り替えたいときは、そのウィンドウの「別のフォルダ…」か、 ビューアの「プロジェクト」タブから追加・切り替えができます。
アプリの中には CLI も同梱しています。端末からも使いたい場合はこれを PATH に置けます:
sudo ln -sf /Applications/Strata.app/Contents/MacOS/strata-cli /usr/local/bin/strata
strata --versiondmg を手で入れたい場合(インストーラを使わないとき)
最新リリースの
Strata-macos-arm64.dmg を開き、Strata.app を Applications へドラッグしたあと、
次の 1 行が必要です。
xattr -dr com.apple.quarantine /Applications/Strata.appこれをしないと「"Strata"は壊れているため開けません。ゴミ箱に入れる必要があります。」と出ます。 アプリが壊れているわけではなく(署名の検証自体は通ります)、Apple の公証を受けていないためです。 ダウンロード時に付く隔離属性があると macOS がこう表示します。 macOS 15 (Sequoia) 以降では「右クリック → 開く」では回避できません(Apple が廃止したため)。 上の 1 行インストーラは、この手順まで済ませます。
Node.js のインストール不要。ランタイム同梱の単一実行ファイルです。
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 用は提供していません |
| 同梱ランタイム | Node.js v24.18.0 |
ad-hoc 署名のみ(Apple の公証なし)です。ブラウザでダウンロードした場合は
xattr -d com.apple.quarantine ./strata で隔離属性を外してください。
Intel Mac / Linux / Windows では下記の git clone 版を使ってください(機能は同じです)。
brew tap makoto-developer/strata
brew trust makoto-developer/strata # 公式以外の tap は明示的な信頼が必要(Homebrew の仕様)
brew install strata
strata --version
strata serve /path/to/your-monorepo
brew trustを省くとRefusing to load formula from untrusted tapで止まります。 新しめの Homebrew が、公式以外の tap を既定では読み込まなくなったためです。 Apple Silicon では Node.js 同梱のバイナリが、Intel Mac / Linux ではソース + Homebrew のnodeが入ります(いずれも同じ機能です)。
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-monorepogit 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-monorepostrata serve examples/demo
strata trace examples/demo 'Gateway.handleUser'
strata check examples/demo # 意図的に仕込んだ循環 2 件で exit 1
strata metrics examples/demostrata 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 が高いほど「多くに依存し変更の影響を受けやすい」、低いほど「多くに依存され変更の影響範囲が広い」。
- 構造ビュー: メトロ路線図風の配線 + レベル化 + 地層(strata)バンド。 「上向き依存 = レイヤー違反」「循環依存」が一目で浮かび上がる
- API タブ: gRPC(proto / service / RPC)・⇄HTTP エンドポイント・◈GraphQL フィールドを
1 つのカタログにまとめて表示 + フロー表示。
⚡RPC → 実装ハンドラ → 関数 → ⚡別サービスの RPCをサービス境界越しに辿れる - 図タブ: サービス単位のアーキテクチャ図。依存を関数レベルまで展開できる
- エントリーポイントタブ: プロセス起動点(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 をノード化し、リゾルバ実装(gqlgen / Apollo)、
クライアントの
gql\query`操作、federation のextend type @key` によるサブグラフ間参照を接続 - 循環依存検出(Tarjan SCC)/ レイヤー違反の可視化
- 🛡 gRPC インターセプタ検出: 認可等の横断ミドルウェアを検出し、サービス/フローに表示
- ⚙ 設定サーフェス: 各サービスが要求する環境変数を検出
- ✉ 非同期(Pub/Sub):
messaging設定で publish/subscribe をトピック経由の依存として可視化
- アーキテクチャルール検査: 禁止依存を宣言して 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] |
ビューアを起動(既定 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 <old> <new> [--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 の雛形を生成 |
ワークスペースルートに置きます(すべて任意)。
forbiddenのfrom/toはノード id・ラベルへのグロブ(**/は 0 段以上の階層、*は 1 階層)。 エッジ端とその祖先に照合するので、パッケージ単位のルールが関数エッジにも効きます。 グロブを含まないパターンはパス片(セグメント)単位で一致します(webはweb/src/...に当たり、webhook-inのような部分文字列には当たりません)。messagingを設定するとbus.Publish("order.created", …)のような呼び出しを検出し、publisher → ✉topic → subscriberのイベント辺を張ります。
- 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 .- 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 }# ベースブランチとトピックブランチそれぞれで 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- 1 行 = 1 要素(S=サービス / M=モジュール / P=パッケージ / ⬢ proto / ƒ 関数 / ⚡ RPC / ✉ トピック)。 ▸/▾ で展開・折りたたみ
- 依存は左レーンのメトロ配線。▶ の先が依存先、グレー=下向き(正常)/ローズ=上向き(レイヤー違反)。 破線=RPC / proto / イベント境界、太さ=依存数、赤背景=循環
- 行クリックでフォーカス(緑=依存先, 青=依存元)。関数/RPC を選ぶとコールツリーを表示
- ⭐ ブックマーク: 行の ☆ か
bキーで登録、ヘッダの「★ n」から一覧・ジャンプ - キーボード:
↑↓移動 /→←展開・折りたたみ /Enter開閉 //検索 /Esc閉じる /Alt+←→戻る・進む - サービスを選ぶと、依存先/依存元・公開 API の使用状況・🛡 インターセプタ・⚙ 環境変数を表示。 依存は関数レベルまで展開でき、各関数はクリックで移動
「プロジェクト」タブで複数リポジトリを登録・切替(~/.config/strata/projects.json)。
複合プロジェクトで複数リポを 1 つの依存グラフとして解析できます。
- テキスト・構文レベルの静的解析(型推論なし)。誤検出より取りこぼしを優先する方針で、 グラフに出ている依存は実在するものだけにしている
- サービス間接続は proto を「正」とし、
go_package/ 生成スタブ / RPC 名の突き合わせで接続する - interface 越しの呼び出し・高階関数・リフレクションは追跡しない。
メッセージキュー経由の依存は
messaging設定で検出(未設定なら対象外) - 詳細と各言語の対応範囲: docs/SPEC.md
npm test # CLI・解析エンジン + ビューア/サーバの DOM/HTTP スモーク
npm run typecheck # tsc --noEmit(strict)Strata 本体は実行時依存ゼロですが、開発・配布・ドキュメントでは次の OSS を利用しています (いずれも各リポジトリのライセンスを確認し、条件の範囲内で利用しています)。
| 用途 | プロジェクト | ライセンス |
|---|---|---|
| 実行ランタイム(バイナリに同梱) | Node.js | MIT |
| 単一実行ファイルへの blob 注入 | postject | MIT |
| ビルド時のバンドル | esbuild | MIT |
| 型チェック(devDependency) | TypeScript | Apache-2.0 |
| スクリーンショット・デモ録画(開発時のみ) | Playwright | Apache-2.0 |
| ドキュメントサイトの生成 | Jekyll | MIT |
| ドキュメントサイトのテーマ | Just the Docs | MIT |
| 行動規範の原文 | Contributor Covenant v2.1 | CC BY 4.0(出典表記は CODE_OF_CONDUCT.md に記載) |
esbuild / postject / Playwright は npm install --no-save で都度入れて使う方式にしており、
package.json の依存には含めていません(利用者側のインストールには不要です)。
また、レポートの図生成には Mermaid(MIT)の記法を出力しています (Strata 自体は Mermaid を同梱せず、GitHub 等のレンダラに任せています)。
「依存関係を層(strata)として捉え、レイヤー違反を可視化する」という発想は、 アーキテクチャ可視化ツール一般の考え方に基づくものです。コード・アイコン・文言は すべて本プロジェクトのオリジナルで、他ツールからの流用はありません。
AGPL-3.0-only で提供します(LICENSE)。Copyright (c) 2026 makoto-developer.
- ツールとして使う(実行する)だけなら、個人・企業を問わず無料で自由です
- 改変版の配布や、本ツールを組み込んだサービスの提供にはソース公開義務があります。 別条件(商用ライセンス等)が必要な場合は作者に相談してください
- 貢献の条件は CONTRIBUTING.md を参照
本ツールは完全な独自実装です(他製品のコード・アセットの流用はありません)。
配布物に含まれる第三者コードの表記:
- macOS 向けバイナリには Node.js(MIT)を同梱しています。ライセンス全文は
アーカイブ内の
THIRD-PARTY-NOTICES.txtに同梱しています - ソース配布物に第三者コードは含まれません(実行時依存ゼロ)。開発・ビルドで使う OSS は 使っているもの・謝辞を参照してください
質問・不具合の窓口は SUPPORT.md を参照してください。

{ "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 } }