TECH PLAY

サイオステクノロジー(Tech.Lab)

サイオステクノロジー(Tech.Lab) の技術ブログ

546

はじめに 前回は、StatefulSetと永続ボリューム(PV/PVC)を使い、データが消えないDBコンテナを起動しました。 しかし、データベースはアプリケーションから接続されて初めて価値があります。そのため今回はアプリコンテナとDBコンテナの接続方法を学びます。 前提条件 Kubernetesで、Pod同士をどうやって通信させるのか仕組みを知りたい方 DBコンテナを立てることはできたが使用出来ていない状態の方 アプリコンテナとDBコンテナを接続するための基本概念 コンテナ同士を接続する方法はいくつかありますが、Kubernetesでは推奨される接続方法が決まっており、単純な接続方法ではうまくいきません。特にDB接続では、ポート番号や認証情報(Secret)をアプリコンテナに適切に渡す必要があるほか、DBコンテナの動的なスケーリングや再起動によるIPアドレスの変動が接続安定性の課題となります。 このような固有の課題を解決するためには、Kubernetesのネットワーク層におけるServiceやDNSの仕組みを理解することが重要です。この記事では、DB接続における安定性を向上させるために、ServiceとDNSの利用方法に焦点を当て、その役割や実践的な活用法を解説します。 直接接続の問題点 最も単純な接続方法は、DBコンテナ(Pod)のIPアドレスを調べ、アプリの設定ファイルに直接記述する方式です。しかし、この方法には致命的な問題があります。Podは再起動するとIPアドレスが変わってしまうという点です。ノードの障害、設定変更による再デプロイ、負荷分散による再スケジューリングなどの問題が発生すると、古いPodは破棄され、新しいPodが作られます。この時、IPアドレスは変わってしまいます。 直接接続ではDBが再起動するたびにアプリの設定ファイルを書き換え、再起動しなければならず手間がかかります。 Serviceの仕組み Kubernetesでは、PodのIPアドレスが変動する問題を解決するために「Service」というリソースを利用します。Serviceは一意の名前を持ち、内部DNSを介してアクセス可能です。これにより固定的なDNS名を提供することができ、アプリケーションはこのDNS名を使用して安定した通信を実現できます。 KubernetesのDNSの仕組み Serviceを利用することで、PodのIPアドレスが変わる問題を解決できます。しかし、ServiceのIPアドレスをアプリケーションに設定する手間が残ります。この問題を解決するのがKubernetesのDNSです。通常、DNSはドメイン名とIPアドレスを対応させる役割を持っています。一方、Kubernetesクラスターには専用のDNSサーバーが標準で組み込まれており、Service名とIPアドレスを対応づける機能を提供します。Kubernetesでは、Serviceを作成すると、そのサービス名とIPアドレスの対応が自動的にDNSサーバーに登録されます。 この仕組みによりKubernetesでのPod間の接続は完全修飾ドメイン名(<Service名>.<Namespace名>.svc.cluster.local)を使用して実現できます。サービス名とネームスペース名を指定することで、Pod間通信が可能になります。 また、本記事ではDNSの仕組みの理解のために完全修飾ドメイン名を使用していますが、同じネームスペース内に存在するアプリケーションからServiceに接続する際にはサービス名だけで接続が出来ます。 YAMLファイルの作成例 これまで、アプリコンテナとデータベースコンテナの接続方法について解説しました。ここからは、具体的なYAMLファイルの例を示し、ServicesやKubernetesのDNSをどのように設定するのかについて解説します。 DBコンテナ側の設定 DBコンテナの設定(接続されるコンテナ) apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql spec: serviceName: "mysql-service" replicas: 1 selector: matchLabels: app.kubernetes.io/name: mysql # (A) Serviceはこのラベルを基準にPodを探す。 template: metadata: labels: app.kubernetes.io/name: mysql # (A) Serviceに見つけてもらうためのラベル。 spec: containers: - name: mysql-container image: mysql:8.0 env: # ... 省略 ... ports: - containerPort: 3306 # (B) このPodが待ち受けるポート。ServiceのtargetPortと一致させる。 volumeClaimTemplates: - metadata: name: mysql-storage spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "standard" resources: requests: storage: 1Gi Serviceの設計(接続の窓口) apiVersion: v1 kind: Service metadata: name: mysql-service # KubernetesのDNSに登録される名前。この名前を使って他のコンテナからアクセス可能になる。 spec: selector: app.kubernetes.io/name: mysql # (A) このラベルを持つPodを探す。 ports: - protocol: TCP port: 3306 # クライアントが接続するポート番号。 targetPort: 3306 # (B) Podのコンテナが待ち受けているポート。StatefulSetのcontainerPortと一致させる。 metadata.name: mysql-service :サービス名がKubernetesのDNSに登録されます。このサービス名とネームスペース名があれば他のコンテナから接続ができます。 selector:Serviceが接続先のPodを決定するためのラベルセレクターです。ここでは、`app.kubernetes.io/name: mysql` というラベルが付けられたPodを対象とします。このラベルセレクターを使用してServiceは指定されたラベルを持つすべてのPodに接続します。 port: 3306:クライアントが接続するポート番号です。アプリケーションはこのポートに向けて通信します。 targetPort: 3306:Serviceが受け取った通信を転送するPodの内部ポート番号です。ここでは3306 番ポートに転送されます。 アプリコンテナ側の設定 apiVersion: apps/v1 kind: Deployment metadata: name: wordpress labels: app: wordpress # Podの識別用ラベル。 spec: # ... 省略 ... template: metadata: labels: app: wordpress spec: containers: - image: wordpress:6.2.1-apache name: wordpress env: - name: WORDPRESS_DB_HOST value: mysql-service.default.svc.cluster.local # 完全修飾ドメイン名を使用してDNSで解決する。 # ... 省略(DBのパスワードやユーザーの設定) ... - name: DB_PORT value: "3306" value: mysql-service:Serviceの名前を元にDNSを使ってIPアドレスを解決し、そのIPアドレスに対して接続を試みるための設定です。 おわりに 今回は、ServiceとDNSを活用したコンテナ同士の接続方法について解説しました。これらの技術を利用することで、PodのIPアドレスが変動しても影響を受けることなく、安定した接続を実現できます。  次回からは、Kubernetes内部のデータベースコンテナを外部に公開する方法について、2回にわたり解説していきます。 参考文献 https://kubernetes.io/docs/concepts/services-networking/service/ https://kubernetes.io/ja/docs/concepts/services-networking/dns-pod-service/ https://kubernetes.io/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post コンテナDB実践シリーズ④:アプリコンテナからDBコンテナへの接続 first appeared on SIOS Tech. Lab .
アバター
今号では、sftp コマンドを使ったファイル転送の方法について説明します! sftp とは sftp とは SSH File Transfer Protocol の略であり、暗号化された通信によって安全にファイルを送受信することができる仕組みです。 以前は ftp によるファイルの送受信が主流でしたが、通信を暗号化する仕組みがないため、内容が盗聴される可能性がありました。 そこで、すべてのデータを暗号化して送信することができる sftp が使用されることになりました。 主な用途としては、システム間でのファイルの送受信や、Web サーバへ各コンテンツ (html、css、画像ファイル) のアップロードなどがあります。 なお、今回は Linux や Windows 上のターミナルで sftp コマンドを使う前提で説明します。 基本の書式 リモートサーバへ接続 sftp ユーザ名@ホスト名 の書式で実行します。 例: $ sftp ruser@172.30.10.10 ruser@172.30.10.10's password: Connected to 172.30.10.10. sftp> ※パスワード認証の場合、リモートユーザのパスワードが求められます。 リモートサーバから切断 exit もしくは bye を実行します。 例: sftp> exit 現在のディレクトリ (リモート側) を表示 pwd コマンドを実行します。 例: sftp> pwd Remote working directory: /home/ruser 現在のディレクトリ (ローカル側) を表示 lpwd コマンドを実行します。 例: sftp> lpwd Local working directory: /home/luser ファイル一覧 (リモート側) を表示 ls を実行します。 例: sftp> ls 1.log 2.log 3.log dir1 dir2 ruser-file -l オプションを付けると、各ファイルやディレクトリの詳細を表示します。 sftp> ls -l -rw-rw-r-- 1 ruser ruser 0 Nov 17 01:04 1.log -rw-rw-r-- 1 ruser ruser 0 Nov 17 01:04 2.log -rw-rw-r-- 1 ruser ruser 0 Nov 17 01:04 3.log drwxrwxr-x 2 ruser ruser 6 Nov 17 01:06 dir1 drwxrwxr-x 2 ruser ruser 6 Nov 17 01:06 dir2 -rw-rw-r-- 1 ruser ruser 0 Nov 17 01:04 ruser-file ファイル一覧 (ローカル側) を表示 lls を実行します。 例: sftp> lls 1l.log 2l.log 3l.log local-dir luser-file -l オプションを付けると、各ファイルやディレクトリの詳細を表示します。 sftp> lls -l total 0 -rw-r--r--. 1 luser luser 0 Nov 17 01:05 1l.log -rw-r--r--. 1 luser luser 0 Nov 17 01:05 2l.log -rw-r--r--. 1 luser luser 0 Nov 17 01:05 3l.log drwxr-xr-x. 2 luser luser 6 Nov 17 01:07 local-dir -rw-r--r--. 1 luser luser 0 Nov 17 01:05 luser-file ディレクトリ (リモート側) を移動 cd ディレクトリ名 の書式で実行します。 例: sftp> cd dir1 ディレクトリ (ローカル側) を移動 lcd ディレクトリ名 の書式で実行します。 例: sftp> lcd local-dir 続いて、一番重要なファイル転送についてのコマンドです。 ファイルのダウンロード (リモート→ローカル) get リモート側のファイル名 の書式で実行します。 例: sftp> get ruser-file Fetching /home/ruser/ruser-file to ruser-file sftp> lls 1l.log 2l.log 3l.log local-dir luser-file ruser-file リモート側のファイル名の後に 任意のファイル名 を付けると、そのファイル名で保存されます。 sftp> get ruser-file ruser-file.bkp Fetching /home/ruser/ruser-file to ruser-file.bkp sftp> lls 1l.log 2l.log 3l.log local-dir luser-file ruser-file.bkp ファイルのアップロード (ローカル→リモート) put ローカル側のファイル名 の書式で実行します。 例: sftp> put luser-file Uploading luser-file to /home/ruser/luser-file luser-file 100% 0 0.0KB/s 00:00 sftp> ls 1.log 2.log 3.log dir1 dir2 luser-file ruser-file リモート側のファイル名の後に 任意のファイル名 を付けると、そのファイル名で保存されます。 sftp> put luser-file luser-file.bkp Uploading luser-file to /home/ruser/luser-file.bkp luser-file 100% 0 0.0KB/s 00:00 sftp> ls 1.log 2.log 3.log dir1 dir2 luser-file.bkp 複数ファイルの一括ダウンロード (リモート→ローカル) mget リモート側のファイル名パターン の書式で実行します。 例: sftp> mget *.log Fetching /home/ruser/1.log to 1.log Fetching /home/ruser/2.log to 2.log Fetching /home/ruser/3.log to 3.log sftp> lls *.log 1.log 2.log 3.log 複数ファイルの一括アップロード (ローカル→リモート) mput ローカル側のファイル名パターン の書式で実行します。 例: sftp> mput *.log Uploading 1l.log to /home/ruser/1l.log 1l.log 100% 0 0.0KB/s 00:00 Uploading 2l.log to /home/ruser/2l.log 2l.log 100% 0 0.0KB/s 00:00 Uploading 3l.log to /home/ruser/3l.log 3l.log 100% 0 0.0KB/s 00:00 sftp> ls *.log 1l.log 2l.log 3l.log sftp コマンドのオプション sftp コマンド の基本的なオプションをご説明します。 ※すべてのオプションはご紹介せず、よく使用されると考えられるものを抜粋しています。 -i 秘密鍵のファイル 公開鍵認証で接続する場合、-i の後に使用する秘密鍵のファイルを指定します。 $ sftp -i ~/.ssh/id_rsa ruser@172.30.10.10 -P ポート番号 SSH/SFTP が 22番ポート (デフォルト) 以外で動作している場合、該当するポート番号を指定します。 $ sftp -P 10022 ruser@172.30.10.10 -v 接続時の詳細なデバッグ情報を表示します。 なお、このオプションには 3段階あり、-vv にするとさらに詳細なデバッグ情報が、-vvv にすると最も詳細なデバッグ情報が表示されます。 $ sftp -v ruser@172.30.10.10 次号について 次号では、sftp と同じくファイル転送を担う rsync についてご紹介します! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 知っておくとちょっと便利!sftp コマンドを使ったファイル転送 first appeared on SIOS Tech. Lab .
アバター
こんにちは! 今月も「OSSのサポートエンジニアが気になった!OSSの最新ニュース」をお届けします。 11/4、LPI-Japan は Linux 技術者認定「LinuC」の上位認定「LinuC レベル3 プラットフォームスペシャリスト」と「LinuC レベル3 セキュリティスペシャリスト」の提供を開始すると発表しました。 LPI-Japan、Linux技術者認定「LinuC」の上位認定を刷新 https://japan.zdnet.com/article/35240027/ 11/4、日経新聞の Slack に不正ログインが確認され、約1万7000人分の情報が流出した可能性があると発表しました。 業務用チャット「スラック」への不正ログインと情報流出について https://www.nikkei.co.jp/nikkeiinfo/news/information/1393.html 11/14 (米国時間)、Red Hat は 新バージョン RHEL 10.1 および RHEL 9.7 の一般提供を開始しました。 Red Hat、Red Hat Enterprise Linux最新版で現代 IT に向け進化した基盤を提供 https://www.redhat.com/ja/about/press-releases/red-hat-delivers-evolving-foundation-modern-it-latest-version-red-hat-enterprise-linux ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【2025年11月】OSSサポートエンジニアが気になった!OSS最新ニュース first appeared on SIOS Tech. Lab .
アバター
こんにちは、サイオステクノロジーの佐藤 陽です。 先日、毎年恒例のMicrosoft Igniteが開催され、様々な機能のリリースが発表されました。 今回は、その中でも個人的にインパクトが大きいと感じた「Foundry IQ」を取り上げます。 なお、本記事は現時点で公開されている紹介記事やドキュメントを読んだうえでの 所感ベース 自分が気になった点に特化 とした内容になっています。 実際に触ってみての検証は今後別途まとめる予定ですので、その点ご承知おきください。 Foundry IQとは Foundry IQは 「a unified knowledge layer for agents(エージェントのための統一された知識レイヤー)  を提供する 」 と述べられています。 この定義をパッと聞いただけだと「結局これは何なの?」といった点が分かりづらいですよね。 そこでまず、現状のRAGの課題を整理し、それをFoundry IQがどう解決しようとしているのかを順番に見ていきます。 現状のRAGの課題 これまでRAGにおいて独自のナレッジを扱うにあたっては、以下のような理由から複雑な構成・運用になりがちでした。 ナレッジの内容ごとのパイプライン設計 ナレッジに対するアクセス制御の複雑さ   Foundry IQは、これらの課題を解決するために設計されています。 1.ナレッジごとのパイプライン設計の負担 ナレッジを格納する際、すべてのデータに対して同じ処理を行っていては、期待する回答精度が得られないことが多いです。 例えば、以下のような観点で処理を変えたくなります。 ファイル形式の多様性: PDF、Office系ファイル、画像、音声 etc. データ構造の違い: 図表が多いファイル or 文章が多いファイル 専門性の違い: 専門用語が多いファイル or 一般的な情報が多いファイル これらの違いによって、データによって前処理の内容やチャンクサイズ、ベクトル化の際の次元数などを適切に切り替えていく必要があります。 また、1つの会社内で導入するにあたって、この「ナレッジの性質」は部署ごとに様々です。 それぞれの部署ごとにこう言ったパイプラインを細かく設計する必要がありますし、 新しくRAGを利用したい部署が出てきた場合、また部署のデータの特性に合わせて新規にパイプラインを設計・構築する必要があります。 また、上記の図はIndexer側の処理の話でしたが、Retrieverも同様です。 ナレッジごとに検索手法(キーワード検索、ベクトル検索、ハイブリッド検索、リランキング方法 etc.)を切り替える必要が出てきます。 このように、データの種別ごとにIndexerやRetrieverをここに設計し、メンテナンスしていくことは RAGを運用していくチームにとっても非常に大きな負担となっています。 2.アクセス制御の複雑さ 様々なナレッジをナレッジストアに登録したとしても、すべてのユーザーがすべてのナレッジにアクセスしてよいとは限りません。 例えば、役員会議用の資料をナレッジストアに登録した場合、一般社員はそのナレッジをコンテキストとした回答は得られないようにするべきです。 現状、Azure AI SearchなどでEntra IDと連携したアクセス制御を「フルマネージドで」実現することは難しく、 自前でEntra IDの情報とAI Search上のデータを紐づけてアクセス制御を実装・運用していく必要があります。 ただ、社内における部署異動や権限の追加/削除など、IDまわりの運用は日々変化します。 それらをすべてRAG側で追いかけ続けるのは、RAGの運用チームにとって大きな負担になります。 このように、既存のRAGでナレッジを適切に運用していくためにはかなりの時間とエネルギーを要します。 これが、今のRAG開発が持つ一番の「辛み」だと感じています。 Microsoft Igniteで発表されたFoundry IQ こうした課題を解決してくれるのがAzure Foundry IQです。 一言で言ってしまうと、「ナレッジごとのパイプライン構築」や「複雑なアクセス制御の実装」といった部分を、いい感じに一括してFoundry IQ側で引き取ってくれるサービス、というイメージです。 (※あくまでイメージ図です) このようにしてFoundry IQ では、RAGまわりの世界観を次のように変えます。 「ナレッジベース(Knowledge Base)」という箱をまず作る そこに、Blob / SharePoint / Web などのデータソースを「つなぐ」 この時点で様々なパイプライン設計・実装をFoundry IQで吸収する 複数のエージェントやアプリケーションから、このナレッジベースを 1つのAPI として参照する つまり、エージェント側やアプリケーション側でIndexerやRetriverの複雑なパイプラインを考慮数る必要はなく 1つのAPIにアクセスすることで、容易にナレッジを利用できるようになります。 Microsoftが出している Foundry IQのブログ記事 のタイトルも「 Unlocking ubiquitous knowledge for agents 」となっており、 まさにこういった部分を狙った機能であることがうかがえます。 Foundry IQの注目ポイント コンセプトは分かったとして、実際何が嬉しいのか? 特徴的だと感じたポイントを3つに絞って見ていきます。 1.データ投入とナレッジ管理 Foundry IQでは、インデックスされたデータとリモートデータをまたいで、同一のナレッジベースとして管理することが可能です。 データタイプ データソース例 インデックス型ソース Blob Storage, Azure AI Search Indexes etc. リモートソース M365 SharePoint, Web etc. このうちインデックス型データソースに対しては、コンテンツの取り込み、チャンク戦略、ベクトル化などを一通り自動で行ってくれます。 そして、これらのデータソースごとにパイプラインを構築したり、Retrieverの戦略を個別に設計したりする必要はない、と述べられています。 つまり、「取り込みたいデータソースをポータル上で選ぶだけで、あとはデータの内容に基づいてよしなにやってくれる」ようなイメージです。 また、リモートソースをそのまま読みに行けるのも大きなポイントです。 これまではSharePoint上のデータについても、一度BlobなどにコピーしたうえでAI Searchにインデックスするのが一般的でした。 この場合、元データの更新と同期をとる必要があり、どうしても処理が複雑になりがちでした。 その点、リモートデータを直接見に行き、常に最新のデータを参照できるのは非常に大きな強みだと思います。 余談 これまでのAzure AI Searchにも「データのインポート」機能があり、ワンクリックでデータのインデクシングを行うことができました。 Foundry IQは、これをより強化した機能、というイメージで個人的には捉えています。 公式ドキュメントにもFoundry IQの基盤はAzure AI Searchである旨の記載があります。 おそらく、AI Searchのデータインポート機能にLLMの力を組み合わせることで、より最適なチャンキングなどを行っているのではないかと予想しています。 2.Agentic Retrieval(エージェント型検索) 次のポイントは、検索エンジン自体が「エージェント化」しているという点です。 従来のRAGは、ざっくり言えば、 ユーザーの質問をEmbeddingする ベクトルDBから類似ドキュメントをk件取る LLMに「質問+コンテキスト」を渡して回答させる というフローが基本でした。 Foundry IQ が掲げている Agentic Retrieval では、ここに「プランニング」と「反復」が入り込みます。 質問の意図を解釈し、 どのデータソースから どの順番で どの粒度で 取ってくるべきかを推論する 初回検索で十分なコンテキストが得られなければ、クエリを書き換えて再検索する 必要に応じて、関連するサブクエリを自動的に発行する さらに、内部パラメータとして「どの程度深く考えてから答えるか(Retrieval Reasoning Effort)」を調整できるようになっています。 FAQレベルの簡単な質問 → 浅く・速く 複雑な推論や調査タスク → 深く・時間をかけて といったユースケースごとのチューニングが可能になるイメージです。 3.アクセス制御 最後はアクセス制限に関してです。 普段RAGの開発をしている自分からすると、ここが一番大きなポイントに感じています Microsoftのブログには、ざっくり次のような点が記載されています(意訳)。 設定済みかつサポートされているナレッジソースに対するユーザー権限を尊重する。 リモートSharePointナレッジソースの場合、Microsoft Purviewのデータ分類と機密ラベルが、インデックス作成および検索パイプラインを通じて尊重される。 今まで自前で制御しなくてはならなかったアクセス制御の部分を、Foundry IQ側で巻き取ってくれるのはこの上なくありがたいです。 なお1.の「設定部分」に関してはまだ詳細を追いきれていませんが、Entra ID基盤上に構築されているサービスであることを踏まえると ここは簡単に設定できる方向で仕上げてくれることに期待したいところです。 ブラックボックス化というトレードオフ ここまで読むと、 Foundry IQ さえ使っておけば間違いないのでは? という印象を持たれるかもしれません。 ただ、エンジニア視点で見ると、「チューニングの余地がかなり減ってしまった」という印象も受けました。 RAG の世界には、職人芸に近いチューニングポイントがいくつもあります。 チャンクサイズとオーバーラップ率 階層構造チャンク / セマンティックチャンクの使い分け Embeddingモデルの選定(汎用 vs ドメイン特化) 再ランキングのON/OFF、スコアのしきい値 Foundry IQ はこういった部分を大幅に巻き取ってくれている一方で、 逆に言えば、これらに直接手を入れる余地は意図的に小さくなっています。 極端に専門用語が多い業界 規制産業で、誤答率を極限まで下げたい案件 などでは、 もう少しRAGの中身を触らせてほしい… という欲求が出てくるかもしれません。 FoundryIQのようにブラックボックス的に大半の処理を行ってくれるのは大きな強みですが、同時に「RAG職人の腕の見せ所が減る」という側面もある点は、頭の片隅に置いておいたほうが良さそうです。 とはいえ、最近のAIの進歩を考えると、「RAG職人」が頑張って細かいチューニングをするよりも、AIに任せた方が良いアウトプットを出す可能性も十分にあります。 このあたりは、実際に使ってみて評価していくフェーズかなと思います。 導入時の注意ポイント 最後に、これは Foundry IQ に限らず、すべてのRAGに言える話ですが、 Garbage In, Garbage Out の原則は、一切変わりません。 元のデータソース管理場所がゴミ屋敷状態 新規 (1).docx 、 最終版_本当に今度こそ最終.pptx が乱立し、どれが最新か分からない 権限設定が形骸化 「よく分からないので Everyone にフルアクセスつけました」 といった環境のまま Foundry IQ とつなぐと、 高い確率で「自信満々に間違ったことを言うエージェント」か、 「見せてはいけない情報をさりげなく提案してしまうエージェント」が生まれます。 Foundry IQ は、 接続と検索エンジンの負担を大きく軽減してくれる ツールですが、 「データガバナンスそのものを自動で何とかしてくれる魔法」ではありません。 むしろ、Foundry IQ のようなツールを導入したとしても、 情報資産の棚卸し メタデータ設計 権限ポリシーの整理 といった 地味だが本質的な仕事 は結局必要になる、という印象です。 まとめと今後 今回はMicrosoft Igniteで発表された「Foundry IQ」についてご紹介しました。 Foundry IQを利用することによって、これまで煩雑な設計・管理が必要だった部分が大幅に削減されることが期待できます。 一方で、それによってチューニングポイントがかなり減ってしまうため、 特殊な業界のユースケースなど、マネージドな仕組みだけでは対応しきれないケースも出てくるかもしれません。 今回はMicrosoftの紹介記事を読んでの所感ベースかつ、RAGに特化した内容でした。 次回以降は実際にFoundry IQを使ってみつつ、エージェントとして使うならではの部分や・使ってみた感想などをお伝えできればと思います。 ではまた! 参考文献 Foundry IQ: Unlocking ubiquitous knowledge for agents Foundry IQ: ナレッジを最大限活用する Foundry IQ ナレッジ ベースを Foundry Agent Service に接続する ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 1人がこの投稿は役に立ったと言っています。 The post Foundry IQ は RAGにとっての銀の弾丸となりえるか?【Microsoft Ignite 2025 Recap】 first appeared on SIOS Tech. Lab .
アバター
こんな方へ特におすすめ ストップウォッチ作成の記事 を読んだ方 自作アプリを初期起動と共に実行させたい方 簡単にPythonのアプリを開発したい方 概要 こんにちは。サイオステクノロジーのはらちゃんです!今回9本目のブログ執筆です。 前回はストップウォッチアプリを開発しました。しかし、コードのままだと逐一コマンドで起動する必要があり面倒です。 そこで今回は、もっと便利に活用するために自動で起動させる方法を簡単3ステップでお伝えします。 EXE化ってなに? はじめに、”EXE(エグゼ)化”という変換の概要をご説明します。 EXE化とは、 「 プログラミング言語(Pythonなど)の翻訳機と、プログラムの指示書をひとまとめにして、誰でもワンクリックで動かせる状態にすること 」 です。 EXE化の仕組み stopwatch.py はただの「設計図」のようなもので、動かすにはPythonという「工具」と、Tkinterという「部品」が必要です。そのため、EXE化する前のプログラム単体ではアプリを起動させることができません。 PyInstallerは、「設計図(スクリプト)」「工具(Python本体)」「部品(ライブラリ)」の全てを一つにまとめて、 StopWatch.exe という「完成品(実行ファイル)」を製造します。 そのため、EXE化の工程を経てようやくアプリがどこでも起動できる準備が整います。 この仕組みはよく料理に例えられます。 「レシピ(指示書)」を動かすには、受け取る相手のPCに「キッチン(Python環境)」と「調理器具(ライブラリ)」が完備されている必要があります。 相手側で用意する手間を省くために、このレシピをプロのシェフごと箱詰めにして「お弁当」にするのです。 EXE化のメリット・デメリット 項目 EXE化のメリット EXE化のデメリット 起動 ダブルクリック一発 展開処理の時間がかかる 配布 相手にファイルを渡す ファイルサイズが大きくなる コード ダブ中身が見えにくくなる コードの修正ができない 前提条件 Windows 上で作業すること Python 3.8+ がインストールされていること pyinstaller をインストール可能であること Step1:EXE化 さっそく箱詰めしていきましょう。 .bat ファイルの作成 この.batファイルは、PythonスクリプトをEXEファイルに変換する「PyInstaller」というツールを実行するためのものです。 これを実行すると、 stopwatch.py から StopWatch.exe を作成します。 build_windows.bat @echo off REM PythonのEXE化ツール「PyInstaller」をインストールします pip install pyinstaller echo. echo --- Building StopWatch.exe --- echo. REM PyInstallerを実行します REM --onefile: 関連ファイルをすべて1つのEXEにまとめます REM --noconsole: GUIアプリ実行時に後ろで黒いコンソール画面が出ないようにします pyinstaller --onefile --noconsole --name StopWatch stopwatch.py echo. echo --- Build finished! --- echo `dist` フォルダ内に `StopWatch.exe` が作成されました。 echo. pause Step2:スタートアップへの登録 .ps1 ファイルの作成 この.ps1ファイルは、EXEファイルをWindowsの「スタートアップ」フォルダに登録し、PC起動時に自動実行するためのスクリプトです。 create_shortcut.ps1 param( [string]$TargetPath = "C:\Users\YourName\Documents\TIMER\dist\StopWatch.exe", [string]$ShortcutName = "StopWatch.lnk" ) # (以下は変更不要) $startup = [Environment]::GetFolderPath('Startup') $w = New-Object -ComObject WScript.Shell $sc = $w.CreateShortcut((Join-Path $startup $ShortcutName)) $sc.TargetPath = $TargetPath $sc.WorkingDirectory = Split-Path $TargetPath $sc.Save() Write-Host "Shortcut created in: $startup" Step3:実行 いよいよアプリの起動です。以下のコードを順に実行してください。 必ず、Windows上で作業するように注意してください。WSL(Linux)上でPyInstallerを実行しようとしてもエラーになります。 PowerShell # "cd" の後に、stopwatch.pyがあるフォルダのパスを入力します cd C:\Users\YourName\TIMER もしコードがWSL上にあるなら、Windows上にダウンロードされるようにツールのインストールも行ってください。 PowerShell pip install pyinstaller PowerShell pyinstaller --onefile --noconsole --name StopWatch stopwatch.py これでEXEファイルが作成できました! 最後に、.ps1 ファイルの2行目にある、$TargetPathをビルド結果のパスに書き換えてます。 create_shortcut.ps1 param( # ↓↓↓ この行のパスを書き換える ↓↓↓ [string]$TargetPath = "C:\Users\YourName\Documents\TIMER\dist\StopWatch.exe", [string]$ShortcutName = "StopWatch.lnk" ) # (以下は変更不要) 修正したスクリプトを実行します。 PowerShell .\create_shortcut.ps1 これで、Windowsのスタートアップフォルダにショートカットが作成されました。 PCを 再起動 してみてください。 ログイン後、自動的にストップウォッチ ( StopWatch.exe ) が起動し、デスクトップの常に一番手前に表示されれば、すべての作業は完了です。 エラー解決 PowerShellのセキュリティエラーです。 Windowsが、信頼できる作成元(Microsoftなど)によって署名されていないスクリプトの実行をデフォルトでブロックしている ために発生しています。 以下のコマンドを実行して、 今開いているこのPowerShellの画面(プロセス)だけ 、一時的にスクリプトの実行を許可します。 PowerShell Set-ExecutionPolicy Bypass -Scope Process 上記コマンドを実行した後、もう一度スクリプトを実行します。 PowerShell .\create_shortcut.ps1 振り返り:前回の開発環境 前回のストップウォッチ開発では、dev-containerを開発環境として用意していました。 dev-containerは、ホストOSから隔離されたネットワーク環境を持っています。 そのため、どこでも同じように動くクリーンな環境が出来上がります。 しかし、この「隔離」が原因で、コンテナーのGUIをPC本体の画面に映し出すために、Xサーバーの設定が必要となりました。 このように、dev-containerを使わないほうが開発が楽な場合もあると学びになりました…。 まとめ 今回は自作アプリをEXE化することと、それを使ってWindows上でアプリを自動起動させることを学んできました。 本ブログで書かれている開発コードは、私の Github に公開しているので自由にコードを書き替えて使ってみてくださいね。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post EXE化の使い方|Pythonで作ったアプリの自動起動 first appeared on SIOS Tech. Lab .
アバター
はじめに ども!Claude Codeを執筆に贅沢活用している龍ちゃんです。やっと Playwright MCP を触る機会ができました。話題になってただけあって、 めちゃくちゃ便利 ですね。 前回の記事「 Claude Code SkillでHTML図解を自動生成!時短テクニック 」で、Claude CodeにHTMLで図解を作ってもらう方法を紹介したんですが、 スクリーンショットの手間が面倒 じゃないですか。ブラウザで開いて、サイズ合わせて…って。しかも僕、DevContainer環境でブログ書いてるんで、いい感じに開けないんですよね。 そこで Playwright MCPを使ったら、さくっと実装してくれた んです。これは感動しました。 Playwright MCPは、Microsoft公式のModel Context Protocol (MCP)サーバーで、Claude CodeからPlaywrightのブラウザ自動化機能を直接呼び出せます。スクリーンショット取得はもちろん、ページ遷移、フォーム入力、要素のクリックなど、22個ものツールが使えます。 ただ、セットアップ方法が「npx版」「Docker Compose版」「Docker直接実行版」と3種類あって、 正直どれ選べばいいかわかんない ですよね。 僕自身、Node.jsが使える環境とPythonしか使えない環境でそれぞれ開発してて、「どっちにも適用したいけど、どうしよう?」って悩んだんです。そこで今回、npx版とDocker版それぞれのセットアップを検証しました。 この記事では、 環境別に最適なPlaywright MCPのセットアップ方法 を紹介します。開発環境、本番環境、DevContainer環境など、それぞれのケースでどの方式を選べばいいかを明確にしていきます。 すべての設定ファイルと詳細なREADMEは、 GitHubリポジトリ で公開しています(npx版、Docker Compose版、Docker直接実行版すべて含む)。 この記事で伝えたいこと 環境に合わせて最適なPlaywright MCPのセットアップ方法を選べるようになります。 この記事で扱う内容 : 3つのセットアップ方式(npx版、Docker Compose版、Docker直接実行版)の比較 環境別の推奨方法(開発環境、本番環境、CI/CD、DevContainer) すぐ試せるコード例(コピペ可能な設定ファイル) DevContainerでの2つの選択肢(npx vs Docker) Playwright MCPの基本 Playwright MCPとは Playwright MCPは、Microsoft Playwrightチームが公式に提供するMCPです。Claude CodeからPlaywrightのブラウザ自動化機能を直接呼び出せます。 パッケージ情報 : npm : @playwright/mcp バージョン : 0.0.47(2025年11月14日公開) ライセンス : Apache-2.0 メンテナー : Microsoft Playwright公式チーム 主な機能 Playwright MCPはコアツール20個に加え、タブ管理とブラウザインストールの計22個が標準で利用可能です。さらに、 --caps フラグでopt-inすることで、座標ベース操作、PDF生成、テストアサーション、トレーシングなど追加11個(合計33個)のツールが使えます。 本記事では、コアツールのうち以下の7個を実際に検証しました: ツール 機能 用途 browser_navigate ページ遷移 URLを開く browser_snapshot ページ構造取得 DOM情報を取得 browser_take_screenshot スクリーンショット PNG画像を保存 browser_console_messages コンソールログ取得 デバッグ情報の確認 browser_evaluate JavaScript実行 カスタムスクリプト実行 browser_install ブラウザインストール Chromiumのセットアップ 残り15個のツール (要素操作、高度な機能)は未検証ですが、公式ドキュメントによると以下のような機能があります: 要素操作: browser_click , browser_type , browser_fill_form タブ管理: browser_tabs , browser_close ファイル操作: browser_file_upload 3つのセットアップ方式 方式の比較表 項目 npx版 Docker Compose版 Docker直接実行版 Node.js必須 必要 不要 不要 Docker必須 不要 必要 必要 セットアップ時間 5分 5分(初回)、10秒(2回目以降) 中程度 設定ファイル .mcp.json のみ compose.yml + .mcp.json .mcp.json のみ ディスク使用量 約300MB 約1GB 約1GB メモリ消費 低(数百MB) 中〜高(約1GB、常駐) 低(使用時のみ) 起動速度 1-2秒 1-2秒 中程度 環境別推奨マトリクス ユースケース 推奨方式 理由 個人開発(単一プロジェクト) npx版 セットアップ簡単、高速、安定 チーム開発(開発環境) npx版 .mcp.json で共有可能 複数プロジェクト共有(開発) Docker Compose版 常駐型で複数プロジェクトから利用 本番環境 Docker直接実行版 公式推奨、セキュア、独立実行 CI/CD Docker直接実行版 クリーン環境、再現性、並列実行 DevContainer環境 npx版 stdio接続、Node.js標準搭載 方法1: npx版(開発環境推奨) 設定ファイル(コピペ可能) プロジェクトルートに .mcp.json を作成します: { "mcpServers": { "playwright": { "type": "stdio", "command": "npx", "args": [ "@playwright/mcp@latest", "--headless", "--isolated", "--browser", "chromium", "--no-sandbox" ] } } } 重要なフラグ : @latest : 常に最新版を使用(本番環境では @0.0.47 等のバージョン固定を推奨) --headless : DevContainer/Docker環境で必須(GUI表示不可能な環境) --isolated : プロファイルロック問題を回避( 必須フラグ ) --browser chromium : ブラウザを明示的に指定 --no-sandbox : DevContainer/Docker環境で必須 セキュリティ警告 : --no-sandbox フラグはChromiumのサンドボックス保護を無効化します。DevContainer/Docker環境では必須ですが、本番環境での使用は慎重に検討してください。 セットアップ手順(5分) Step 1 : 上記の .mcp.json をプロジェクトルートに作成 Step 2 : VSCodeをリロード Cmd/Ctrl + Shift + P → “Developer: Reload Window” Step 3 : Chromiumをインストール npx playwright install chromium ダウンロードサイズ: 約174MB 所要時間: 約30秒 Step 4 : 動作確認 Claude Codeで以下のように依頼します: Playwright MCPを使用して、https://example.com を開いてページタイトルを取得してください 期待される結果 : ページURL: https://example.com ページタイトル: “Example Domain” エラーなし メリット・デメリット メリット(開発環境) : インストール不要 – npx経由で即座に実行 公式サポート – Microsoft公式チームがメンテナンス 最新版自動取得 – @latest で常に最新 高速・軽量 – 1-2秒で起動(開発環境で検証済み) チーム共有簡単 – .mcp.json をGit管理 構造化アプローチ – アクセシビリティツリー使用 デメリット・制約 : 開発環境向け – 本番環境での使用は未検証 初回起動遅い – パッケージダウンロード(数秒〜数十秒) ネットワーク依存 – インターネット接続必要(初回/ @latest 使用時) Node.js必須 – Node.js v20以上が必要 キャッシュ管理 – npm cacheに約300MB消費 推奨ケース npx版が最適 : 個人開発(単一プロジェクト) チーム開発( .mcp.json 共有) DevContainer環境 頻繁な使用(開発中) プロトタイピング・検証 npx版を本番環境で使用する場合の推奨事項 : 本記事では主に開発環境での使用を検証していますが、本番環境で使用する場合は以下の対策を推奨します: バージョン固定 : @latest ではなく @0.0.47 等の具体的なバージョンを指定 十分な検証 : 負荷テスト・セキュリティ検証を実施 監視体制 : エラーハンドリング・監視体制を構築 障害対策 : ネットワーク障害時の挙動を確認 より安全な本番環境運用には、Docker直接実行版の検討もご検討ください(セキュリティ重視、クリーン環境)。 方法2: Docker Compose版(常駐型・開発環境向け) compose.yml(コピペ可能) プロジェクトルートに compose.yml を作成します: services: playwright-mcp: image: mcr.microsoft.com/playwright:v1.49.1-noble container_name: playwright-mcp-server ports: - "8931:8931" environment: - PLAYWRIGHT_BROWSERS_PATH=/ms-playwright - PLAYWRIGHT_CHROMIUM_ARGS=--no-sandbox --disable-setuid-sandbox command: > sh -c " npx playwright install chrome && npm install -g @playwright/mcp@latest && npx @playwright/mcp@latest --port 8931 --headless --isolated --no-sandbox " restart: unless-stopped networks: - mcp-network networks: mcp-network: name: mcp-network driver: bridge .mcp.json(コピペ可能) { "mcpServers": { "playwright": { "command": "docker", "args": [ "exec", "-i", "playwright-mcp-server", "node", "/root/.npm/_npx/9833c18b2d85bc59/node_modules/.bin/mcp-server-playwright", "--isolated", "--no-sandbox" ] } } } 注意 : npxのパス( /root/.npm/_npx/... )は環境により異なる場合があります。 パスの確認方法 : docker exec -it playwright-mcp-server bash find /root/.npm/_npx -name "mcp-server-playwright" パスが異なる場合は、 .mcp.json の該当箇所を更新してください。 セットアップ手順 Step 1 : 上記の compose.yml をプロジェクトルートに作成 Step 2 : サーバー起動 docker compose up -d 初回: 約5分(イメージ743MB + Chrome 112MB) 2回目以降: 約10秒 Step 3 : 上記の .mcp.json を作成(npxパスを確認) Step 4 : VSCodeをリロード メリット・デメリット メリット : 複数プロジェクト共有 – 常駐型で複数から利用可能 環境分離 – Dockerコンテナで独立 自動再起動 – restart: unless-stopped 管理が簡単 – Docker Composeで一元管理 stdio接続 – docker exec経由で安定した通信 デメリット : 初回起動時間 – 約5分(イメージ743MB + Chrome 112MB) リソース常時消費 – メモリ・CPU常駐(約1GB) npxパス依存 – パスが環境により異なる可能性 Docker知識必要 – Docker/Docker Composeの理解が必要 推奨ケース Docker Compose版が適している場合 : 複数のプロジェクトで共有したい 開発環境での頻繁な使用 チーム全体で統一環境を使用したい リソースを常時確保できる環境がある npx版が適している場合 : 単一プロジェクトでのみ使用 リソース消費を最小限に抑えたい Docker環境を構築したくない 安定したパフォーマンスが必要 方法3: Docker直接実行版(都度起動型・本番環境推奨) .mcp.json(コピペ可能) { "mcpServers": { "playwright": { "command": "docker", "args": [ "run", "-i", "--rm", "--init", "--pull=always", "mcr.microsoft.com/playwright/mcp", "--isolated" ] } } } 特徴とメリット 特徴 : 公式イメージ : mcr.microsoft.com/playwright/mcp 実行方式 : docker run --rm (終了後自動削除) セッション毎に新しいコンテナ : 完全に独立 公式ドキュメントで紹介 : セキュリティ重視の場合に適した方式 メリット : 最もセキュア – セッション毎に独立 リソース効率的 – 使用時のみ起動 常に最新 – --pull=always で最新イメージ クリーン – --rm で自動削除 本番環境向け設計 推奨ケース Docker直接実行版が適している場合 : 本番環境 – セキュリティ重視 CI/CD環境 – クリーンな環境、再現性 各実行が独立が必要 – テストの独立性 リソース効率重視 – 使用時のみリソース消費 常に最新版を使用 – 自動更新が必要 他の方式が適している場合 : npx版 – Node.js環境があり、高速起動が必要(開発環境) Docker Compose版 – 複数プロジェクトで共有、常駐型が必要(開発環境) コラム:DevContainerでの選択 DevContainer環境でPlaywright MCPを使う場合、2つの選択肢があります。僕自身、最初はどちらを選べばいいか迷ったんですが、実際に両方試してみて分かったことをシェアします。 選択肢1: npx版をコンテナ内に収める 設定例 ( .mcp.json ): { "mcpServers": { "playwright": { "type": "stdio", "command": "npx", "args": [ "@playwright/mcp@latest", "--headless", "--isolated", "--no-sandbox" ] } } } メリット : シンプル – DevContainerにはNode.js標準搭載 高速 – ネットワーク経由不要、stdio接続 設定が簡単 – .mcp.json のみ デメリット : Node.js必須 – DevContainerにNode.jsが必要 コンテナサイズ増加 – npm cache約300MB 選択肢2: Docker版をホストで動かす 設定例 (Docker Compose版の場合): DevContainerの devcontainer.json でホストDockerソケットを共有: { "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ] } .mcp.json は「方法2: Docker Compose版」と同じ。 メリット : Node.js不要 – DevContainerにNode.jsが不要 リソース分離 – ホスト側でブラウザ実行 デメリット : Docker socket共有が必要 – セキュリティ考慮が必要 設定が複雑 – devcontainer.json の編集が必要 ネットワーク経由 – やや遅延が発生する可能性 どちらを選ぶか 僕の推奨: npx版をコンテナ内に収める 理由は以下の3つです: DevContainerにはNode.js標準搭載 わざわざDockerソケット共有の設定をする必要がない 高速で安定 stdio接続なので、ネットワーク経由の遅延がない シンプル .mcp.json だけで完結 Docker版が必要なケース : Node.jsを使わないプロジェクト(Python専用など) リソースを完全に分離したい 複数のDevContainerプロジェクトで共有したい 実際の使い方 Claude Codeでの基本操作 セットアップが完了したら、Claude Codeで以下のように依頼するだけで使えます: 例1: ページを開いてスクリーンショット Playwright MCPを使って、https://playwright.dev を開いて、スクリーンショットを撮影してください 例2: ページタイトルを取得 Playwright MCPで https://example.com のページタイトルを取得してください パフォーマンス・動作確認データ(参考) 動作確認(npx版、開発環境で検証) : 操作 時間 結果 ブラウザ起動(初回) 1-2秒 ブラウザ起動(2回目以降) < 1秒 example.com ナビゲーション < 1秒 playwright.dev ナビゲーション < 2秒 スクリーンショット取得 < 1秒 3つの方式のパフォーマンス比較 : 操作 npx版 Docker Compose版 ブラウザ起動 1-2秒 1-2秒 ページアクセス < 1秒 27-94秒(ばらつき大) スクリーンショット < 1秒 < 1秒 初回セットアップ 約30秒 約5分 結論 : 実用上は大きな差はありませんが、 npx版の方が安定している 印象です。Docker Compose版はページアクセスにばらつきがあるので、開発環境で頻繁に使うならnpx版がおすすめです。 驚くほど高速でした。 特にnpx版は、開発環境での使用であれば非常に安定しています。 トラブルシューティング 問題1: プロファイルロックエラー エラーメッセージ : Error: Browser is already in use for /home/node/.cache/ms-playwright/mcp-chrome-* use --isolated to run multiple instances of the same browser 解決策 : .mcp.json に --isolated フラグを追加 VSCodeをリロード 予防策 : 最初から --isolated を含める(強く推奨) 問題2: MCPサーバーが認識されない 解決策 : .mcp.json の構文確認(JSONバリデーター使用) VSCodeをリロード Claude CodeのOutputパネルでエラーログ確認 問題3: Chromiumが起動しない 解決策 : npx playwright install chromium Chromiumがインストールされていない場合は、上記コマンドで手動インストールしてください。 問題4: Docker Compose版でnpxパスが見つからない 解決策 : docker exec -it playwright-mcp-server bash find /root/.npm/_npx -name "mcp-server-playwright" パスを確認して、 .mcp.json を更新してください。 まとめ 今回は、Playwright MCPの環境別セットアップ方法を紹介しました。 環境別の選択ガイド 開発環境(個人・チーム) : npx版 セットアップ簡単(5分) .mcp.json だけで完結 高速・安定 開発環境(複数プロジェクト) : Docker Compose版 常駐型で複数から利用 環境分離 本番環境/CI/CD : Docker直接実行版 公式推奨 セキュア クリーン環境 DevContainer環境 : npx版 Node.js標準搭載 stdio接続で高速 この記事で実現できたこと 環境に合わせた最適なセットアップ方法の選択 コピペで試せる設定ファイル DevContainerでの選択肢(npx vs Docker) トラブルシューティング より詳しく知りたい方へ : すべての設定ファイルと詳細なREADMEは、 GitHubリポジトリ で公開しています(npx版、Docker Compose版、Docker直接実行版すべて含む)。 次のステップ 前回の記事「 Claude Code SkillでHTML図解を自動生成!時短テクニック 」で紹介したHTML図解の作成と、今回のPlaywright MCPセットアップを組み合わせることで、 HTML→PNG変換の完全なワークフロー が実現できます。 次回は、この HTML→PNG変換の詳細 について解説する予定です。Playwright MCPを使った自動スクリーンショット取得、画像最適化、ブログへの埋め込みまでの一連の流れを紹介します。 皆さんも、ぜひPlaywright MCPでブラウザ自動化にチャレンジしてみてください!質問や感想は、コメント欄でお待ちしております。 参考リンク 公式ドキュメント Playwright MCP GitHub npm パッケージ Playwright公式サイト MCP仕様 前提記事 Claude Code SkillでHTML図解を自動生成!時短テクニック HTML図解の自動生成方法 Tailwind CSS + Material Iconsの活用 PNG変換の基本 GitHubリポジトリ playwright-mcp-sample 3つのセットアップ方法の完全なサンプルコード DevContainer対応 すべて動作検証済み 詳細なREADME(日本語) MITライセンス 次に読むべき記事 HTML→PNG変換の詳細 (次回予定) Playwright MCPを使った自動スクリーンショット 画像最適化のベストプラクティス ブログへの埋め込みワークフロー 最後まで読んでいただき、ありがとうございました! この記事が役に立ったら、ぜひSNSでシェアしてください。質問やフィードバックは、 @RyuReina_Tech や @SIOSTechLab でお待ちしています! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Playwright MCPで始めるブラウザ自動化|環境別セットアップガイド first appeared on SIOS Tech. Lab .
アバター
はじめに:指示をさぼりたい どうも、Claude Codeとべったりな龍ちゃんです。 最近、Claude Codeが選択肢式の出力を出してきて、質問に答えたらいい感じに指示を分類してくれたりしてたんですよ。調べたら、どうやら9月ぐらいに発表された機能らしくて。 「これ毎回発火してくんねーかな」 って思ったんですよね。 AI使うことでだいぶ楽になったんですけど、人間って怠惰なんで。指示をちゃんと打ち込めば動くのはわかってるんですけど、エージェント発火させたりスキル発火させたりするのを すげえさぼりてえな って。 僕、今 ブログのエージェント を何個か作っていて、タイトルやメタディスクリプションを作ったり、ブログのレビューとか技術情報収集とか、いろんなエージェントがあるんですけど。それぞれ一個ずつ発火させるのって クソ面倒臭い ですよね。 それが選択肢式で、「選択肢出して」って言ったら出してくれて、ぼちぼち設定できたら いいな って思って、こんなブログを書いてます。 で、調べてわかったことなんですけど、 全然失敗することもある らしいんですよね。僕の環境でもめちゃくちゃ失敗してるんで、まあ今後に期待したいみたいな話で、ちょっと先んじて書いておこうかなって思ってます。 注意点としては : まだまだ開発中というか、品質として良いとは言えない状態 すぐ取り込むのは良くないんじゃないかな 発火したらラッキーと思ってるぐらいがちょうどいい この画面、見たことありますか? Claude Codeが質問してくれるやつです。 でも現実は… これを確定で発火させて、Skillsとして提供しておいて、どのエージェント発火するかをCLI的に選ぼうみたいな とち狂ったこと を書いていきます。 具体的にどうするのかと、このツールのちょっと参考になる情報を、さっくりまとめていこうかなと思ってます。もしもあれなら参考にしてもらえればなと。 AskUserQuestionツールって何? AskUserQuestion は、タスク実行中に対話的な質問をするためのツールです。 (2025年11月時点のClaude Code v2.0.46で動作確認済み) 理想的な動作: ユーザーに選択肢を提示 ユーザーが選択(単一または複数) 回答を受け取って処理を分岐 実装例: AskUserQuestion({ questions: [ { question: "この記事の現在の状態を教えてください", header: "記事の状態", multiSelect: false, options: [ { label: "初稿完成(技術チェック必要)", description: "書き上げたばかりで、技術的正確性とセキュリティを確認したい" }, // ... 他の選択肢 ] } ] }) 詳しい作り方は Claude Codeに聞いてみて! (どうせ今後変わるかもしれないし) 現実:めちゃくちゃ失敗する 調査したところ、 AskUserQuestion は現状かなり不安定 でした。 既知の問題: ✗ 公式ドキュメントに包括的な説明なし ✗ スキル内で初回呼び出し時に失敗 ✗ “User answered Claude’s questions:” と表示されるが実際には質問しない ✗ 空の応答で処理が完了してしまう △ プランモード切り替えで一時的に機能することがある(不安定) GitHubイシュー: #9846: AskUserQuestion tool doesn’t work in skill until plan mode toggled #9912: Can’t trigger AskUserQuestion tool #9854: Related duplicate issues ツールが発火しなかった時にどうするか その時はまあ、サボらず、ちゃんとプロンプトを打ち込もうな って話ですね。 ちゃんと動かしたら、エージェントとかSkillsとか出てきて、だいぶ言うこと聞いてくれるようになったり、作業が自動化されたりしてるんで。その辺ね、多少プロンプトサボっちゃダメですよ。 回避策 SkillsとかAgentがちゃんと発火しないとき: description でどうにかする CLAUDE.md にちゃんと説明を書く 例えば、 CLAUDE.md にこんな感じで書いておく: **⚠ レビュー依頼の処理方法**: ユーザーが記事のレビューを依頼した場合(「レビューして」「チェックして」「確認して」など)、 以下のエージェントを**直接呼び出さず**、必ず`.claude/skills/review-article.md`スキルを発火させてください: - blog-reviewer - content-reviewer - technical-accuracy-reviewer - seo-title-generator review-articleスキルがユーザーの意図を確認し、適切なエージェントを選択します。 こういうことで、まあ大体はできるので。 僕の実装例:review-article.md スキル 参考までに、僕が作った review-article.md スキルを紹介します。 やりたいこと: 「この記事をレビューして」だけで、適切なエージェントを選びたい 4つのエージェント(技術チェック、品質改善、SEO、タイトル生成)を使い分けたい 理想的な動作: AskUserQuestion で記事の状態を質問 どのレビュー項目を実行するか選択(複数選択可) 選択に基づいて適切なエージェントを順次実行 現実: AskUserQuestionが動かない でもキーワードトリガー(「レビューして」など)は動く CLAUDE.mdで制御すれば、まあまあ使える 詳しい実装は Claude Codeに聞いてみて! (長いので) まとめ 「Claude Codeへの指示を少しでもさぼりたい」という正当な欲求から生まれた実験。 現状: AskUserQuestionは不安定 でも将来的には期待できそう 今は代替策でなんとかする 推奨: キーワードトリガーを活用 CLAUDE.mdで制御 ちゃんとプロンプトを打ち込む ✗ AskUserQuestionに依存しない 学び: スキル・エージェント連携の実装パターンは参考になる フォールバック戦略は重要 発火したらラッキー、ぐらいの気持ちで 「さぼりたい」という気持ちは、エンジニアリングの原動力です。理想と現実のギャップを理解しつつ、現実的な代替策で効率化を追求していきましょう。 ぜひ面白コンテンツだと思って読んでもらえればなと思います。 参考リンク 公式ドキュメント: Claude Code CLI Reference – Anthropic Docs Claude Code GitHub Repository 既知の問題: #9846: AskUserQuestion tool doesn’t work in skill until plan mode toggled #9912: Can’t trigger AskUserQuestion tool #9854: Related duplicate issues ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Claude Codeへの指示を少しでもさぼりたい!AskUserQuestionツール first appeared on SIOS Tech. Lab .
アバター
この記事では、AzureMCPServerとStreamlitを組み合わせて、Azureリソースを対話的に操作するWebアプリケーションを構築する方法について説明します。 つまり以下のように「Azureのコレコレのリソースの情報取得して」とか「Azure Blob Storageのコンテナ作って」みたいにWebブラウザから対話的に指示すると、そのとおりにAzureリソースが出来上がるWebアプリをサクッと作ってしまおうという感じです。 説明はいいからサクッと動かしたいよーという方はソースコードと起動方法を以下のGitリポジトリで公開しているので、そちらを参照してください。 https://github.com/noriyukitakei/azure-mcp-server-webif Azure MCP Serverとは? Azure MCP Serverとは、Azureが提供しているMCPサーバーであり、Azureリソースの管理や操作を行うための機能を提供します。 https://learn.microsoft.com/ja-jp/azure/developer/azure-mcp-server/tools/ MCP(Model Context Protocl)に準拠しているので、MCPに対応しているクライアントであれば、Visual Studio CodeやCursor、Eclipse、IntelliJなど、様々な開発環境からAzureリソースを操作することができます。 今回構築するWebアプリケーションについて Visual Studio Code などから Azure MCP Server と連携する例は多く紹介されていますが、本記事では Streamlit を使って Web インターフェースを構築し、Azure MCP Server と連携する方法 を紹介します。これにより、ブラウザ上から Azure リソースを対話的に操作できるようになり、より多くのユーザーにとって使いやすいインターフェースを提供できます。 ただし、適切な権限管理を行わないと、意図しない Azure リソースの変更が発生する可能性があるため注意してください。 今回構築するアプリのソースコードは以下のGitHubリポジトリで公開しています。 https://github.com/noriyukitakei/azure-mcp-server-webif.git 構成 今回構築するシステムの構成は以下の通りです。 UIを提供するStreamlit、LLMによる思考を担うAIエージェント、MCPクライアント、Azure MCP Serverの4つのコンポーネントで構成されます。UI、AIエージェント、MCPクライアントは同一のWebアプリケーション(プロセス)内で動作し、Azure MCP Serverとの通信方式はSTDIO(標準入出力)を使用します。 UI Webアプリケーションのユーザーインターフェース部分です。Streamlitを使用して構築します。ユーザーからの入力を受け取り、結果を表示します。 Streamlitは、Pythonを使って簡単にインタラクティブなWebアプリケーションを作成できるオープンソースのフレームワークです。プログラミングの経験が少なくても、Pythonコードを書くだけで、データビジュアライゼーションやインターフェースを持つアプリをすぐに作ることができるのが特徴です。 従来、Webアプリケーションを作成するには、フロントエンド(HTML、CSS、JavaScript)とバックエンド(Python、Django、Flaskなど)の両方の技術を理解する必要がありました。しかし、Streamlitを使えば、Pythonだけでフロントエンドとバックエンドを同時に構築できるため、非常に手軽にアプリ開発に取り組めます。 たとえば、データサイエンティストがモデルの結果を共有したり、エンジニアがプロトタイプを素早く作成したりする場面でよく利用されています。 AIエージェント ユーザーからの指示を受け取り、適切なアクションを判断し、必要に応じてMCPサーバーにリクエストを送信します。 Function Callingを活用し、AIエージェントの思考と行動を実現します。Function Callingに対応したLLMを使用する必要があるため、今回は Azure OpenAI Serviceを利用しますが、他の対応LLMに置き換えることも可能です。 なお、AIエージェントは LangChainのようなAIエージェントフレームワークを用いて実装することもできます。しかし今回は学習を目的として、できるだけシンプルな独自実装で進めます。そのため、コードはやや冗長であり、実際のアプリケーションで使用するには最適化が必要な部分もありますが、基本的な仕組みを理解するには十分な内容になっています。 MCPクライアント MCPクライアントは、FastMCPを用いて実装しています。FastMCP は、MCPサーバーとMCPクライアントの両方の機能を提供するライブラリであり、ここではMCPクライアントとして使用します。 MCPサーバー Azure MCP Server本体になります。Azureリソースの管理や操作を行うための機能を提供します。npxやnpm、Dockerで起動する方法がありますが、今回はDockerで起動し、通信方式はSTDIO(標準入出力)を使用します。 処理の流れ 今回構築するWebアプリケーションの処理の流れは以下の通りです。 [ステップ1] ユーザーが指示を入力 ユーザーはWebアプリケーションのUIを通じて、Azureリソースに対する操作指示を入力します。例えば「ストレージ アカウント ‘ntakeiassets’ のコンテナー ‘images’ の ‘log4j.png’ の詳細を教えて」と入力するとします。 その指示は、StreamlitによるUIを通じてAIエージェントに送信されます。 [ステップ2] MCPサーバーへの初期化要求 MCPクライアントは、initializeというメソッドで初期化メッセージを最初に送ります。これは、MCPクライアントがMCPサーバーに対して「自分の機能・情報・バージョンなどを伝えて、接続を初期化したい」とリクエストしているメッセージです。 [ステップ3] MCPサーバーからの初期化応答 MCPサーバーはinitializeリクエストを受け取り、初期化応答を返して、自身のプロトコルのバージョンなどをMCPクライアントに伝えます。 [ステップ4] 初期化完了通知の送信 MCPクライアントは、MCPサーバーからの初期化応答を受け取り、初期化が完了したことをMCPサーバーに通知します。 [ステップ5] ツールの一覧取得 MCPクライアントは、tools/listというメソッドでツールの一覧(そのMCPサーバーが持っている機能の一覧)をMCPサーバーにリクエストします。これにより、MCPサーバーが提供するツールの情報を取得します。 [ステップ6] ツール一覧の応答受信 MCPサーバーは、tools/listリクエストを受け取り、提供するツールの一覧をMCPクライアントに返します。ここではAzure MCP Serverが提供するツールの一覧(Azure Blob StorageやAzure AI Searchなどのリソースを操作するコマンド一覧)が返されます。 [ステップ7] LLMへのFunction Calling指示 AIエージェントは、MCPクライアントから渡されたツール一覧をもとに、LLMに対してFunction Callingを行うよう指示します。具体的には、ユーザーからのプロンプトを解析してどのツールを呼び出すべきかを判断し、そのツールを使うようLLMに指示します。 ここでは、ユーザーの質問である「ストレージ アカウント ‘ntakeiassets’ のコンテナー ‘images’ の ‘log4j.png’ の詳細を教えて」とともに、tools/listで取得したツール一覧をLLMに渡します。 [ステップ8] LLMからの関数呼び出し応答 LLMは、AIエージェントからのFunction Calling指示を受け取り、適切な関数呼び出し応答を生成します。この応答には、呼び出す関数名とそのパラメータが含まれます。 ここでは、sotorageというツールをLLMが選択したことがわかります。これはAzure Blob Storageの情報を取得するためのツールであり、ユーザーの質問に対して適切な選択となります。 [ステップ9] MCPサーバーへの関数呼び出しリクエスト AIエージェントはLLMからの関数呼び出し応答を受け取り、MCPクライアントを介してMCPサーバーに関数呼び出しリクエストを送信します。これにより、MCPサーバーに対して指定された関数を実行させます。 [ステップ10] MCPサーバーからの関数呼び出し応答 MCPサーバーは、MCPクライアントからの関数呼び出しリクエストを受け取り、指定された関数を実行します。その結果をMCPクライアントに返します。 今回は、Azure Blob Storageのさらに細かいコマンド一覧が返されています。 つまり、1回目のツール一覧取得では大まかなツール一覧が返され、2回目の関数呼び出し応答では、さらに詳細なコマンド一覧が返される形となっています。 [ステップ11] LLMへの追加Function Calling指示 ステップ11で取得した詳細なコマンド一覧をもとに、AIエージェントはLLMに対して追加のFunction Callingを行うよう指示します。これにより、ユーザーの質問に対してさらに具体的な回答を生成するための情報を提供します。 [ステップ12] LLMからの関数呼び出し応答 LLMは、AIエージェントからの追加Function Calling指示を受け取り、適切な関数呼び出し応答を生成します。この応答には、呼び出す関数名とそのパラメータが含まれます。 以下のような応答が返され、Azure Blob Storageの特定のコンテナ内にあるファイルの詳細情報を取得するための関数呼び出しが示されています。 "function_call": {   "name": ”storage_blob_get",   "arguments": "{'account': 'ntakeiassets', 'container': 'images', 'blob': 'log4j.png'}" } つまりこれは、storage_blob_getというコマンドを用いて、ストレージアカウント ‘ntakeiassets’ のコンテナ ‘images’ 内の ‘log4j.png’ というファイルの詳細情報を取得するための関数呼び出しを意味しています。 [ステップ13] MCPサーバーへの関数呼び出しリクエスト AIエージェントはLLMからの関数呼び出し応答を受け取り、MCPクライアントを介してMCPサーバーに関数呼び出しリクエストを送信します。これにより、MCPサーバーに対して指定された関数を実行させます。 [ステップ14] Azure Resource ManagerへのAPIリクエスト MCPサーバーは、MCPクライアントからの関数呼び出しリクエストを受け取り、そのコマンドをAzure Resource Manager (ARM) へのAPIリクエストに変換して実行します。これにより、Azureリソースに対する操作が行われます。 [ステップ15] MCPサーバーからの関数呼び出し応答 MCPサーバーは、Azure Resource ManagerからのAPIレスポンスを受け取り、その結果をMCPクライアントに返します。 今回は、指定されたストレージアカウント、コンテナ、ファイルに関する詳細情報が返されます。これには、ファイルのサイズ、作成日時、更新日時、コンテンツタイプなどのメタデータが含まれています。 [ステップ16] LLMへの最終Function Calling指示 AIエージェントはMCPクライアントからの関数呼び出し応答を受け取り、LLMに対して最終的なFunction Callingを行うよう指示します。これにより、ユーザーの質問に対する最終的な回答を生成するための情報を提供します。 [ステップ17] LLMからの最終応答 LLMは、AIエージェントからの最終Function Calling指示を受け取り、ユーザーの質問に対する最終的な応答を生成します。この応答には、Azureリソースに関する詳細情報が含まれています。 そして、AIエージェントはこの最終応答をWebアプリケーションのUIに返します。 起動方法 処理の流れをご理解いただけたところで、実際にアプリケーションを起動して動作させてみましょう。以下の手順で進めてください。 [ステップ1] リポジトリのクローン まず、GitHubリポジトリをクローンします。ターミナルを開き、以下のコマンドを実行してください。 $ git clone https://github.com/your-repository-url.git $ cd your-repository-directory [ステップ2] 環境変数の設定 次に、必要な環境変数を設定します。 `.env.example` ファイルをコピーして `.env` ファイルを作成し、必要な値を設定してください。 $ cp .env.example .env .env ファイル内で設定する主な環境変数は以下の通りです。 AZURE_OPENAI_ENDPOINT : Azure OpenAI ServiceのエンドポイントURL AZURE_OPENAI_API_KEY : Azure OpenAI ServiceのAPIキー AZURE_OPENAI_API_VERSION : 使用するAPIバージョン (例: 2024-06-01) AZURE_OPENAI_CHAT_DEPLOYMENT : 使用するチャットモデルのデプロイメント名 (例: gpt-4)` MAX_STEPS : AIエージェントが実行する最大ステップ数 (例: 5) AZURE_TENANT_ID : AzureテナントID AZURE_SUBSCRIPTION_ID : AzureサブスクリプションID AZURE_CLIENT_ID : AzureクライアントID AZURE_CLIENT_SECRET : Azureクライアントシークレット AZURE_OPENAI_ENDPOINT 、 AZURE_OPENAI_API_KEY 、 AZURE_OPENAI_CHAT_DEPLOYMENT は、Azure OpenAI Serviceに接続するための情報となります。これはLLMにFunction Callingを実行させるために必要です。 AZURE_TENANT_ID 、 AZURE_SUBSCRIPTION_ID 、 AZURE_CLIENT_ID 、 AZURE_CLIENT_SECRET は、Azure MCP ServerがAzureリソースにアクセスするための情報となります。これらの値はAzureポータルでアプリケーション登録を行い、サービスプリンシパルを作成することで取得できます。そして、そのサービスプリンシパルに対して必要なAzureリソースへのアクセス権限を付与してください。例えば、ストレージアカウントの情報を取得する場合は、「ストレージ アカウント閲覧者」ロールを付与します。 MAX_STEPS は、AIエージェントが実行する最大ステップ数を指定します。これにより、無限ループを防止できます。もしこれを設定しないと、AIエージェントが過剰に多くのステップを実行し、Azure OpenAI Serviceにすごいい数のリクエストを送ってしまう可能性があります。結果、コストが高額になる恐れがあるため、適切な値を設定してください。 [ステップ3] 依存関係のインストール 次に、必要なPythonパッケージをインストールします。以下のコマンドを実行してください。 $ pip install -r requirements.txt [ステップ4] アプリケーションの起動 ブラウザで http://localhost:8501 にアクセスし、Azureリソースに対する操作指示を入力してみてください。例えば、「ストレージ アカウント ‘ntakeiassets’ のコンテナー ‘images’ の ‘log4j.png’ の詳細を教えて」と入力すると、アプリケーションがAzure MCP Serverと連携して情報を取得し、結果を表示します。 まとめ いかがでしょうか。Webブラウザから対話的にAzureリソースを操作できるのは非常に便利です。Azure MCP ServerとStreamlitを組み合わせることで、ユーザーにとって使いやすいインターフェースを提供できます。こんな感じで今後も、Azureの様々なサービスと連携したWebアプリケーションを構築していきたいと思います。ぜひ皆さんも試してみてください。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Azure MCP ServerとStreamlitでAzureを対話的に操作するWebアプリ first appeared on SIOS Tech. Lab .
アバター
はじめに 前回はKubernetesにおけるデータ永続化について解説しました。 今回は、実際にKubernetesのデータ永続化機能を利用してKubernetes上でDBコンテナを起動する方法をハンズオン形式で紹介します。 今回の構成 以下の図1は、今回のハンズオンで作成するKubernetesでMySQLのようなデータベースを安定して動かすための仕組みを表しています。 図1:StatefulSetで構成されたMySQLコンテナの概念図 前提条件 kubectlが使用可能である minikubeがインストール済み バージョン:v1.36.0 使用するMySQLコンテナ イメージ:MySQL:8.0 事前準備 今回のハンズオンで使用するsample_mysql.ymlを以下に記載します。 apiVersion: v1 kind: Service metadata: name: mysql-service labels: app: mysql spec: ports: - port: 3306 name: mysql clusterIP: None selector: app: mysql --- apiVersion: v1 kind: Secret metadata: name: mysql-secret type: Opaque stringData: mysql-root-password: "mysql_root_password" --- apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql-statefulset spec: serviceName: "mysql-service" replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:8.0 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: mysql-root-password volumeMounts: - name: mysql-persistent-storage mountPath: /var/lib/mysql volumeClaimTemplates: - metadata: name: mysql-persistent-storage spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "standard" resources: requests: storage: 1Gi 主要なパラメーター sample_mysql.yml内の主要なパラメーターについて説明します。 kind: Service Kubernetesにおいてネットワークサービスを定義するためのオブジェクトです。今回のファイルではmysqlというラベルがついたPodをサービスの管理対象とすると指定しています。 kind: Secret パスワードなどの機密情報を安全に格納し、Podに環境変数として渡すために使用されるKubernetesリソースであるSecretを設定します。今回のファイルではmysqlのパスワードなどを格納しています。 kind: StatefulSet ステートフルなアプリケーションのデプロイと管理を行うために使用されるKubernetesリソースであるStatefulSetを設定します。StatefulSetはPodに固有の識別子を与えたり、安定したストレージを保証する設定を行うことでDBコンテナ運用において重要な役割を果たしています。 volumeClaimTemplates Podごとに永続ボリューム要求(PVC)を動的に作成するためのテンプレートを定義する、StatefulSetに特有のフィールドです。今回はこのフィールドで永続ストレージを確保するための設定をしています。 metadataはPVCの「名前」などのメタデータを定義します。 今回は『name: mysql-persistent-storage』で名前を定義しています。 specでは仕様の定義を行います。 accessModes: [ “ReadWriteOnce” ]ではアクセスモードを指定します。ReadWriteOnceは1つのノードからの読み書き可能という仕様の設定です。 storageClassName: ストレージクラスとは、Kubernetesでストレージの種類や動作を指定するための設定テンプレートです。今回はストレージのクラスをstandardに設定します。 resourcesのstorage: 1Giではストレージの容量として1Giを要求しています。 Kubernetes上でMySQLコンテナを起動 StatefulSetを利用してMySQLコンテナをminikube上にデプロイ minikube startコマンドを実行し、minikubeを起動します。 minikube start minikubeの起動 kubectl applyはYAMLやJSONなどの設定ファイルをKubernetesクラスターに適用し、リソースの状態を管理するためのコマンドです。このコマンドを使用してsample_mysql.ymlをKubernetesクラスターに適用します。 kubectl apply -f "sample_mysql.yml" 設定ファイルの適用 Podと永続ボリューム(PV/PVC)の状態を確認  kubectl getコマンドはKubernetesクラスター内のリソースの一覧を取得するコマンドです。このコマンドを使用することで、Pod、PVC(PersistentVolumeClaim)、PV(PersistentVolume)の状態を確認できます。 kubectl get pods を実行することで、Podの一覧とそれぞれのステータスを確認できます。`STATUS`の個所にRunningと表示されていれば正常に稼働していることを示します。 kubectl get statefulsetsを実行することで、StatefulSetが正常に動作しているか確認できます。特に`READY`の値が期待される数と一致している場合正常に動作していると確認できます。 kubectl get pvcとkubectl get pvを実行することで、PVCとPVの状態を確認できます。PVCとPVがBound状態であれば、ストレージが正常に割り当てられていることを示します。また、`CLAIM`フィールドには対応するPVCやPVの名前が記載されており、どのリソースがストレージを利用しているかを確認できます。さらにStatefulSetではvolumeClaimTemplatesによってPodごとに固有のPVCが作成され、専用のPVと1対1で紐づくことにより各Podが専用の永続ストレージを持つことができます。 kubectl get pods kubectl get statefulsets kubectl get pvc kubectl get pv Kubernetesクラスター内のpodの状態確認 SratefulSetの状態確認 PVCの状態確認 PVの状態確認 データが永続化されていることを確認 データの永続化が正しく機能しているか確認するために今回はMySQLコンテナ内に新しいデータベースを作成します。 kubectl exec -it "kubectl get podsで取得したpod名" -- mysql -uroot -p CREATE DATABASE "任意のデータベース名"; 初期状態のデータベース 新しいデータベースを作成 次に、Podを削除して再作成される様子を確認します。この手順では、Podが削除されてもストレージ永続化の仕組みによってデータが保持されていることを検証します。StatefulSetではPodが削除されても同じ名前のPodが再作成され、PVCやPVもそのPodに紐づいた状態を維持します。 kubectl delete pod "pod名" podの削除と再作成の確認 Podは削除すると自動で再作成されます。Podの再作成後MySQLコンテナ内に入り、作成したデータベースが残っているかを確認します。データベースが残っていたらKubernetesのストレージ永続化が正しく機能しています。 データの永続化の確認 おわりに 今回はハンズオンを通して、StatefulSetとPV/PVCの利用により、コンテナ環境で安全にDBを運用する方法を紹介しました。 次回はKubernetes上のアプリケーションコンテナがDBコンテナに接続する仕組みについて解説します。 参考文献 https://kubernetes.io/docs/concepts/services-networking/service/ https://kubernetes.io/docs/concepts/services-networking/service/#headless-services https://kubernetes.io/docs/concepts/configuration/secret/ https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/ https://kubernetes.io/docs/reference/kubectl/generated/kubectl_apply/ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post コンテナDB実践シリーズ③:Kubernetesでデータベースを動かしてみた first appeared on SIOS Tech. Lab .
アバター
はじめに ども!Claude Codeにべったりな龍ちゃんです。 前回の記事「Claude Codeの一時ファイルで爆速ビジネスロジック検証:UI不要で要件を発見する方法」 で、tmpスクリプトが「自然言語から生まれた純粋な要件」であることを説明しました。 本記事では、 実際にどうやってtmpスクリプトを観察し、ビジネスロジックを抽出し、CLI機能として昇格させるか を、具体的なコード例とともに解説します。 TL;DR この記事で分かること: tmpディレクトリのプロジェクト内設定方法 デフォルトの問題点(OSの/tmpに生成される) CLAUDE.mdでの設定方法 tools/配下に配置するメリット プロジェクト構成とtmpの配置 4層構造の実装(公式SDK → 自作Client → CLI → Skill) tmpスクリプトがCLIツールを活用する仕組み 実装されたCLIコマンド一覧 posts, categories, hashtags, scheduled-posts, validate操作 Skillsで提供される機能 vs tmpで補完される機能 tmpスクリプトの具体例 ハッシュタグチェック、データクリーニングの実装 DRY RUNモードによる安全性確保 ビジネスロジック抽出の実装手順 tmpから本体コードへの昇格プロセス Operations層、CLI層、Skill層の実装 週次レビューの実践 頻出パターンの分析コマンド docs/research/への記録方法 環境セットアップ Python/uv環境の構築 TypeScript環境の構築 型ヒントによる品質向上 重要な前提条件: 「Claude Code: 公式MCPを補完するSkills設計パターン」と前回の記事を読んでいる Claude Code Skillsの基本を理解している こんな人に読んでほしい 前回の記事を読んで「実際にどう実装するの?」が気になった人 tmpスクリプトの観察を始めたい人 ビジネスロジック抽出の具体的な手順を知りたい人 tmpからCLI機能への昇格プロセスを学びたい人 環境セットアップ(Python/uv, TypeScript)の方法を知りたい人 tmpディレクトリのプロジェクト内設定 デフォルトの問題点 Claude Codeは設定なしだとOSの /tmp ディレクトリにスクリプトを生成してしまいます。これだと: リポジトリ外なので管理しにくい OSの再起動で消える可能性がある 他の開発者と共有できない 履歴が残らない 解決策:リポジトリ内tmpの設定 # tmpディレクトリを作成 mkdir -p application/tools/tmp # .gitignoreでtmpの中身を除外(任意) echo "application/tools/tmp/*.py" >> .gitignore # または、観察目的で意図的にコミットする場合は除外しない CLAUDE.mdに指示を追加 リポジトリルートの CLAUDE.md に以下を追加: ## Temporary Scripts Directory **IMPORTANT**: Always save temporary Python scripts to `application/tools/tmp/` directory. When generating temporary scripts: 1. Place them in `application/tools/tmp/` 2. Use descriptive filenames 3. Include docstrings Example: ```python # application/tools/tmp/validate_data_integrity.py """Temporary script to validate data integrity.""" ``` この設定のメリット tmpスクリプトがリポジトリ内で管理される tools/配下なので同じ依存関係(pyproject.toml)を使える チーム全体で観察可能 gitで履歴管理できる(必要に応じて) プロジェクト構成とtmpの配置 ディレクトリ構造 実際のプロジェクト構成を見てみましょう: application/tools/ ├── src/ │ └── supabase_client/ # 自作Client(ビジネスロジック) │ ├── models.py # データモデル定義 │ ├── operations/ # テーブル操作クラス │ │ ├── posts.py │ │ ├── categories.py │ │ ├── hashtags.py │ │ └── ... │ └── cli.py # CLIコマンド実装 ├── tmp/ # tmpスクリプト(ここ重要!) │ ├── merge_duplicate_categories.py │ ├── validate_orphaned_posts.py │ ├── check_hashtags.py │ ├── remove_hashtags_from_posts.py │ └── ... └── pyproject.toml # 依存関係管理 なぜ application/tools/tmp/ なのか? tmpを tools/ 配下に配置することで、 tmpスクリプトがCLIツールとして実装された機能をそのまま利用できる んです。 実際のtmpスクリプトの中身を見てみると: # application/tools/tmp/check_hashtags.py import subprocess import json def get_all_post_uuids(): """Get all post UUIDs from the database.""" result = subprocess.run( ["uv", "run", "db", "posts", "list", "--limit", "1000"], # ← CLIコマンドを呼び出す capture_output=True, text=True, check=True, ) # Extract UUIDs from output # ... def get_post_details(uuid): """Get post details by UUID.""" result = subprocess.run( ["uv", "run", "db", "posts", "get", uuid], # ← CLIコマンドを呼び出す capture_output=True, text=True, check=True, ) return json.loads(result.stdout) この構造の利点 tmpスクリプトがCLIツール( uv run db コマンド)を組み合わせて使える 依存関係(pyproject.toml)を共有 Claude Codeが生成するスクリプトと本体コードが同じ環境で動作 tmpで検証したロジックをOperations層に抽出しやすい 2つのアプローチ 実際には、tmpスクリプトの実装方法には2つのパターンがあります: 1. CLIコマンド経由 (現在の実装): subprocess.run(["uv", "run", "db", ...]) でCLIを呼び出す 基本操作を組み合わせて複雑な処理を実現 Claude Codeが自然に生成するパターン 2. 直接インポート (より進んだ段階): from src.supabase_client import SupabaseClient で直接インポート Operations層のメソッドを直接呼び出す より複雑なロジックを実装する際に有用 つまり、tmpスクリプトは「使い捨て」じゃなくて、 プロジェクトの一部として機能している んです。 これが、tmpスクリプトから本体機能への昇格がスムーズにできる理由でもあります。tmpスクリプトで検証したロジックを、そのままOperations層( src/supabase_client/operations/ )に移せばいいだけですから。 実装されたCLIコマンド一覧 理解を助けるために、実際に実装されているCLIコマンドを紹介します。tmpスクリプトは、これらのコマンドを組み合わせて複雑な処理を実現します。 投稿(posts)操作 # 投稿一覧取得 uv run db posts list [--limit N] [--blog-url URL] [--pattern N] [--category NAME] [--hashtag NAME] # 投稿詳細取得 uv run db posts get <UUID> # 投稿作成 uv run db posts create --blog-url <URL> --pattern <1-3> --content <TEXT> # 投稿更新 uv run db posts update <UUID> [--content TEXT] [--pattern N] # 投稿削除 uv run db posts delete <UUID> # ブログURL一覧 uv run db posts urls # 統計情報 uv run db posts stats カテゴリ(categories)操作 # カテゴリ一覧 uv run db categories list # カテゴリ作成 uv run db categories create <NAME> # 統計情報 uv run db categories stats # 重複検出 uv run db categories find-duplicates # カテゴリマージ uv run db categories merge --to <ID> --from <IDs> [--dry-run] ハッシュタグ(hashtags)操作 # ハッシュタグ一覧 uv run db hashtags list # ハッシュタグ作成 uv run db hashtags create <NAME> # 統計情報 uv run db hashtags stats # 重複検出 uv run db hashtags find-duplicates # ハッシュタグマージ uv run db hashtags merge --to <ID> --from <IDs> [--dry-run] 予約投稿(scheduled-posts)操作 # 予約投稿一覧 uv run db scheduled-posts list [--status <STATUS>] [--today] [--limit N] # 予約投稿詳細 uv run db scheduled-posts get <UUID> # 予約投稿作成 uv run db scheduled-posts create --text <TEXT> --scheduled-date <ISO8601> [--source-post-uuid <UUID>] # 予約投稿更新 uv run db scheduled-posts update <UUID> [--status STATUS] [--scheduled-date DATE] # 予約投稿削除 uv run db scheduled-posts delete <UUID> データ検証(validate)操作 # 孤立レコード検出 uv run db validate orphaned Skillsで提供される機能の特徴 基本CRUD操作 : 単一レコードの作成・取得・更新・削除 フィルタ機能 : カテゴリ、ハッシュタグ、ブログURLでの絞り込み 統計情報 : 投稿数のカウント、使用状況の可視化 データクリーニング : 重複検出、孤立レコード検出、マージ機能 Skillsで提供されていない機能(→tmpスクリプトで補完) 複雑な組み合わせ処理 : 複数コマンドの連鎖実行 カスタムフィルタロジック : 独自の条件での抽出 一括更新処理 : 条件に基づいた複数レコードの更新 クロスチェック : 複数テーブル横断での整合性チェック この「基本操作」と「組み合わせ処理」の境界が、tmpスクリプトが生成される理由です。 tmpスクリプトの具体例 理論だけでは分かりにくいので、実際のリポジトリにあるtmp/スクリプトを紹介します。 例1: ハッシュタグチェックスクリプト 生成された背景 : 「全投稿のハッシュタグの有無を確認したい」というリクエスト # application/tools/tmp/check_hashtags.py import subprocess import json import re def get_all_post_uuids(): result = subprocess.run( ["uv", "run", "db", "posts", "list", "--limit", "1000"], capture_output=True, text=True, check=True, ) # UUIDを正規表現で抽出 uuids = [] for line in result.stdout.split('\n'): uuid_match = re.search(r'([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})', line) if uuid_match: uuids.append(uuid_match.group(1)) return uuids def has_hashtag(text): return bool(re.search(r'#\w+', text)) # メイン処理: 全投稿をチェックして分類 for uuid in get_all_post_uuids(): post = get_post_details(uuid) if has_hashtag(post['content_text']): with_hashtags.append(post) このスクリプトから分かること : 基本操作の組み合わせ : db posts list → 処理 → db posts get ビジネスルール : 「ハッシュタグあり」= # で始まる単語が含まれる CLIツールの活用 : subprocess.run() でCLIコマンドを呼び出す tmpスクリプトは CLIツールを組み合わせて複雑な処理を実現 していました。 例2: ハッシュタグ削除スクリプト 生成された背景 : 「投稿本文からハッシュタグを削除したい」(データクリーニング要求) # application/tools/tmp/remove_hashtags_from_posts.py import re import subprocess import sys def remove_hashtags(text): # 日本語対応の正規表現でハッシュタグを削除 cleaned = re.sub(r'#[\w\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF]+', '', text) # Clean up multiple spaces cleaned = re.sub(r'\s+', ' ', cleaned) # Remove trailing/leading whitespace cleaned = cleaned.strip() return cleaned # DRY RUNモードで安全確認 execute = '--execute' in sys.argv for post in posts_with_hashtags: new_content = remove_hashtags(post['content_text']) if execute: subprocess.run([ "uv", "run", "db", "posts", "update", post['uuid'], "--content", new_content ]) else: print(f"DRY RUN: Would update {post['uuid']}") print(f" OLD: {post['content_text'][:100]}...") print(f" NEW: {new_content[:100]}...") このスクリプトから分かること : ビジネスルールの具体化 : ハッシュタグ削除の正規表現(日本語対応) 安全性の配慮 : --execute フラグによるDRY RUNモード 一括処理パターン : 取得 → 加工 → 更新 重要な発見 : 同じロジック( remove_hashtags() )が複数のスクリプトで再利用される → これこそ抽出すべきビジネスロジック ビジネスロジック抽出の実装手順 頻出パターンの観察 簡単な分析で、何が必要な機能かが見えてきました: # tmp/内のスクリプトを名前でカウント ls application/tools/tmp/*.py | xargs -n1 basename | sort | uniq -c | sort -nr 結果 : 5 validate_orphaned_posts.py 4 bulk_update_scheduled_posts.py 3 merge_duplicate_categories.py 2 analyze_hashtag_stats.py 1 export_posts_csv.py 解釈 : 5回生成 → 週1回以上使う → Skillに組み込むべき 3-4回 → 定期的に使う → Skill機能追加候補 1-2回 → tmpのままで良い(稀なケース) データが教えてくれました。「validate_orphaned_posts.pyは必要な機能だ」と。 ビジネスロジックの抽出事例 事例1: validate orphaned → Skill機能化 tmpの内容 (5回生成): # tmp/validate_orphaned_posts.py の処理フロー 1. uv run db posts list(全投稿取得) 2. カテゴリ未設定の投稿をフィルタ 3. 結果をリスト表示 発見 : 孤立投稿の検証は定期的に行う作業(週1回以上) ロジックが毎回同じ ビジネスルールが固まっている 「これ、毎回tmpスクリプト生成するの無駄じゃない?Skillに組み込もう」 Skillへの追加(Phase 3実装) : # 新しいコマンドとして実装 uv run db validate orphaned # 出力例 Orphaned Scheduled Posts: 0 Unused Categories: 2 ID: 106, Name: 本番環境構築 ID: 66, Name: フロントエンド Unused Hashtags: 1 ID: 34, Name: #TEST Total issues found: 3 → tmpスクリプトがSkillの本体機能に昇格 これで、次回から「孤立投稿を検証して」と依頼すると、tmpスクリプトを生成せず、直接Skill機能が実行されるようになりました。 事例2: tmpからOperations層への抽出 tmpスクリプトから抽出されたビジネスロジックが、どのように本体コードに統合されるかを見てみましょう。 tmpスクリプトで見つかったパターン → 抽出された実装 : # application/tools/src/supabase_client/operations/hashtags.py """Hashtags table operations""" from supabase import Client from ..models import Hashtag class HashtagOperations: def __init__(self, client: Client): self.client = client self.table = "hashtags" def list(self, limit: int = 100, offset: int = 0) -> list[Hashtag]: result = ( self.client.table(self.table) .select("*") .order("hashtag_name") .range(offset, offset + limit - 1) .execute() ) return [Hashtag(**item) for item in result.data] def count_posts_by_hashtag(self) -> list[dict]: """ Count posts for each hashtag Returns: [ {"hashtag_id": 1, "hashtag_name": "#AI", "post_count": 15}, ... ] """ result = ( self.client.table("post_hashtags") .select("hashtag_id, hashtags(hashtag_name)") .execute() ) # Count posts per hashtag hashtag_counts: dict[int, dict] = {} for item in result.data: tag_id = item["hashtag_id"] tag_name = item["hashtags"]["hashtag_name"] if item.get("hashtags") else None if tag_id not in hashtag_counts: hashtag_counts[tag_id] = { "hashtag_id": tag_id, "hashtag_name": tag_name, "post_count": 0, } hashtag_counts[tag_id]["post_count"] += 1 # Sort by post count descending return sorted( hashtag_counts.values(), key=lambda x: x["post_count"], reverse=True, ) CLIコマンドとしての公開 : # application/tools/src/supabase_client/cli.py import click from .client import SupabaseClient from .operations import HashtagOperations @cli.group() def hashtags(): """Hashtag operations""" pass @hashtags.command("list") @click.option("--limit", type=int, default=10) def hashtags_list(limit: int): client = SupabaseClient() ops = HashtagOperations(client.get_client()) results = ops.list(limit=limit) for hashtag in results: click.echo(f"ID: {hashtag.hashtag_id}, Name: {hashtag.hashtag_name}") @hashtags.command("stats") def hashtags_stats(): """Show hashtag usage statistics""" client = SupabaseClient() ops = HashtagOperations(client.get_client()) stats = ops.count_posts_by_hashtag() click.echo("Hashtag Usage Statistics:") for item in stats: click.echo(f" {item['hashtag_name']}: {item['post_count']} posts") tmpスクリプト → 本体実装の流れ : tmp/check_hashtags.py : ハッシュタグの集計ロジックを発見 Operations層 : count_posts_by_hashtag() としてビジネスロジック化 CLI層 : db hashtags stats コマンドとして公開 Skill層 : Claude Codeから自然言語で操作可能に この4層構造により、tmpスクリプトで検証したロジックが、段階的に本体機能へ昇格していきます。 事例3: 段階的な拡張プロセス tmp観察を続けることで、自然に機能が拡張されていきました: Phase 1(初期実装) : 基本CRUDのみ list, get, create, update, delete tmp観察(1週間) : カテゴリ・ハッシュタグでのフィルタ要求が頻出 統計情報の要求も多い Phase 2(拡張・4時間) : 複雑なクエリ追加 --category , --hashtag フィルタオプション stats コマンド(集計) 中間テーブル操作(add-categories, add-hashtags) tmp観察(さらに1週間) : merge系スクリプトが頻出 データクリーニングの需要が明確に Phase 3(さらに拡張・3時間) : データクリーニング機能 find-duplicates コマンド merge --dry-run コマンド validate orphaned コマンド → tmpの観察が、段階的な機能拡張を自然に導いた 合計開発時間 : 15時間(8 + 4 + 3)でデータベース管理システムが完成(実測例として参考) 週次レビューの実践 頻出パターンの分析 私は毎週金曜日、こんな習慣をつけました: # 頻繁に生成されるスクリプト ls application/tools/tmp/*.py | xargs -n1 basename | sort | uniq -c | sort -nr 観察ポイント : 3回以上生成 → Skill機能追加候補 毎回同じロジック → ビジネスルールが固まっている 微妙に違うパラメータ → オプション化すべき docs/research/への記録 tmp観察ログの例(実際に記録していたもの): # tmp観察ログ: 2024-11-15 ## 今週の傾向 - validate_orphaned_posts.py: 5回生成(先週3回) - merge_duplicate_categories.py: 3回生成(新規) - bulk_update_scheduled_posts.py: 4回生成(継続) ## 発見 - 孤立投稿の検証は定期作業(毎日1回) - カテゴリ重複チェックの需要が増加 - 一括更新のロジックが固まってきた ## ビジネスルール(tmpから抽出) - 重複判定: 類似度90%以上 - マージ優先順位: 投稿数 > 作成日時 > UUID - 孤立投稿: カテゴリ未設定 or ハッシュタグ0個 ## アクション - [ ] db validate orphaned コマンド追加 - [ ] db categories find-duplicates コマンド追加 - [ ] db categories merge --dry-run 実装 この記録が、Phase 2-3の機能拡張につながりました。 UIを作るタイミングの判断 UIが必要になる条件 : 利用者が複数(チームや社内共有) ビジネスロジックが固まっている tmpスクリプトの生成が停止(安定稼働) UIを作る前に確認すること : tmpの観察を2-4週間継続 ビジネスルールが変わらないことを確認 操作フローがtmpから明確に見える 私の場合、まだUIは作っていません。Claude Codeで十分だからです(個人利用のため)。 環境セットアップ tmpスクリプトの品質を高めるために、Claude Codeがコードを書きやすい環境を整えましょう。 Python環境のセットアップ(推奨) なぜPythonなのか : Claude Codeが最も得意な言語 データ処理・バッチ処理に適している スクリプト実行が簡単( uv run python tmp/script.py ) uv環境のセットアップ : # uvのインストール curl -LsSf https://astral.sh/uv/install.sh | sh # プロジェクト初期化と依存関係追加 uv init uv add click pandas requests # tmpスクリプトを実行 uv run python application/tools/tmp/script.py uvのメリット : pipの10-100倍速い / 仮想環境自動管理 / Python自動インストール 詳細な環境構築 : uvで解決!Pythonモノレポの依存関係管理【2025年版】 を参照 TypeScript環境のセットアップ TypeScript/JavaScriptが適しているケース : Node.js環境でのスクリプトに適している フロントエンド・API連携処理に向く # TypeScript環境のセットアップ npm init -y npm install -D typescript ts-node @types/node npx tsc --init # tmpスクリプト用の設定 # tsconfig.json { "compilerOptions": { "target": "ES2022", "module": "commonjs", "outDir": "./dist", "rootDir": "./", "strict": true, "esModuleInterop": true }, "include": ["application/tools/tmp/**/*"] } # tmpスクリプトを実行 npx ts-node application/tools/tmp/script.ts 避けるべき言語 シェルスクリプト(bash): Claude Codeが複雑なロジックを書きにくい Ruby, Perl: サポートは良いが、Pythonの方が安定 Java: セットアップが重く、tmpスクリプトには不向き CLAUDE.mdに言語設定を追加 ## Development Language Preferences **Primary Language: Python 3.12+** - Use `uv run python tmp/script.py` for execution - Leverage type hints for better code generation **Avoid**: Shell scripts for complex logic (use Python subprocess instead) 型ヒントを使う理由 Claude Codeは型情報があると、より高品質なコードを生成します。 # ❌ 型ヒントなし(Claude Codeが推測する必要がある) def get_posts(limit): return client.posts.list(limit=limit) # ✅ 型ヒント付き(Claude Codeが正確に理解) def get_posts(limit: int) -> list[Post]: return client.posts.list(limit=limit) このセットアップのメリット : tmpスクリプトの生成品質が向上 エラーが減り、実行成功率が上がる tmpから本体コードへの移行がスムーズ 型情報により、ビジネスロジックが明確になる tmpスクリプトを保存する習慣 基本方針 Claude Codeが生成したスクリプトを削除しない application/tools/tmp/ に保存して観察する 実行後も残しておく(頻度分析のため) Skill拡張の判断基準 3回以上生成 → 機能追加候補 ロジック固定 → Skill化 1-2回のみ → tmpのまま保持 まとめ tmpからCLI機能への昇格プロセス この5ステップのプロセスにより、tmpスクリプトが段階的に本体機能へ昇格していきます: tmpスクリプト生成 : Claude Codeが自然言語から生成 tmp観察 : 週次レビューで頻出パターンを分析 ビジネスロジック抽出 : Operations層に実装 CLIコマンド化 : CLI層で公開( uv run db ... ) Skill登録 : 自然言語で操作可能に 実践のポイント 環境設定 : tmpディレクトリをリポジトリ内に配置 CLAUDE.mdで明示的に指示 Python/uv環境を整備 観察と分析 : 週次レビューで頻出パターンを把握 docs/research/に記録 3回以上生成 → 機能追加候補 段階的な拡張 : Phase 1: 基本CRUD Phase 2: フィルタ・集計 Phase 3: データクリーニング 次のステップ Claude Code Skills 実装ガイド でCLIツール化とSkill登録の詳細を学ぶ 前回の記事で説明した概念を、本記事の実装パターンで実践してみてください。tmpスクリプトから、あなたのプロジェクトに最適なビジネスロジックが見えてくるはずです。 参考リンク 公式ドキュメント Claude Code 公式ドキュメント Claude Code Skills 公式ガイド Python Click 公式ドキュメント – CLIツール作成 Python Type Hints 公式ガイド uv 公式ドキュメント TypeScript 公式ドキュメント Supabase Python Client シリーズ記事 Claude Code: 公式MCPを補完するSkills設計パターン 4層構造パターン(公式SDK → 自作Client → CLI → Skill) UI開発工数の大幅削減 Claude Codeの一時ファイルで爆速ビジネスロジック検証:UI不要で要件を発見する方法 tmpスクリプトの本質的発見(概念編) なぜUIなしでビジネスロジックを整備できるか 関連ブログ Claude Code Skills 実装ガイド:ローカルツールをスムーズに統合する方法 Skillの実装方法(詳細) Progressive Disclosure、トークン効率化 HTMLでブログ記事を保存してる奴、全員Markdownにしろ。AIが読みにくいでしょうが! blog-scraperの実装例(tmpから進化したツール) トークン削減の実測データ AIチャットで話すだけ!X予約投稿を完全自動化するシステム構築術 X投稿管理システムの全体像 Azure Functions + Supabaseでの予約投稿自動化 質問や感想は、コメント欄でお待ちしております! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Claude Code一時ファイルからSkillsへ:ビジネスロジック抽出の実践ガイド first appeared on SIOS Tech. Lab .
アバター
はじめに ども!Claude Codeにべったりな龍ちゃんです。 前回の記事「Claude Code: 公式MCPを補完するSkills設計パターン」 で、 公式MCPを補完するSkillsパターン を紹介し、UI開発工数を大幅削減した事例を共有しました。 特に、こんな成果を報告しました: フロントエンド開発をスキップ UI設計(3-5日)をスキップ React開発(7-10日)をスキップ 開発工数を大幅削減 (実測例として数時間〜1日で実装) でも、概要しか書いていないので: 「なぜフロントエンド開発をスキップできたの?」 「UIなしでどうやってビジネスロジックを整備したの?」 「短時間で完成した秘密は何?」 前回の記事では「Claude CodeをUIとして使った」と説明しましたが、 それだけでは本質的な理由になっていません 。 本記事では、 なぜフロントエンド開発をスキップできたのか 、その核心に迫ります。 キーワードは、 tmp/ ディレクトリに蓄積されるスクリプトです。 結論を先に言うと、tmpスクリプトは「ゴミ」ではなく、 「人間の自然言語から生まれた純粋な要件」 でした。この発見が、前回の記事で紹介した4層構造(公式SDK → 自作Client → CLI → Skill)を可能にしました。 TL;DR この記事で分かること: なぜUI開発をスキップできたのか の本質的理由 tmpスクリプトがビジネスロジックを整備してくれた Claude Codeが「人間の操作UI」として機能 UIは後回しにできる(ロジック確定後 → 手戻りなし) tmpスクリプトの再定義 従来: tmp/ = 一時的なゴミ 新発見: tmp/ = 人間の自然言語から生まれた純粋な要件の可視化 ロジックファースト検証のプロセス CLI基本実装 → Skill定義 → tmp蓄積 → tmp観察 → ビジネスロジック抽出 → CLI拡張 頻出パターンの発見(5回生成 → Skill化) ビジネスルールの具現化(類似度90%、マージ優先順位等) 実践方法 (詳細は 次回の記事「Claude Code一時ファイルからSkillsへ:ビジネスロジック抽出の実践ガイド」 で解説) 週次レビュー、docs/research/へのログ記録 3回以上生成 → Skill機能追加候補 開発工数削減の本質 AIツールによる速度向上ではない UI開発というアプローチ自体を変えたこと 重要な前提条件: Claude Code Skillsの基本を理解している 前回の記事「Claude Code: 公式MCPを補完するSkills設計パターン」を読んでいる こんな人に読んでほしい 前回の記事を読んで「なぜ短時間で完成できたのか」が気になった人 フロントエンド開発なしでビジネスロジックを整備したい人 application/tools/tmp/ にスクリプトが溜まっている人 要件が固まっていない段階で開発を始めたい人 UI設計の手戻りコストに悩んでいる人 「tmpスクリプト = ゴミ」と思って削除していた人 従来のUI先行開発の問題 まず、典型的な開発フローを見てみましょう: 要件定義 → UI設計 → フロントエンド実装 → バックエンド実装 根本的な問題 : ビジネスロジックが固まっていない段階でUIに投資している 例えば、こんなシーンを想像してください: 要求:「重複カテゴリをマージできる画面が欲しい」 ↓ UI設計開始: ボタン配置、確認ダイアログ、進捗表示... ↓ 実装開始 ↓ 「あれ、重複の定義ってどうするんだっけ?」 「マージ時に投稿数が多い方を残す?古い方を残す?」 ↓ 仕様変更 → UI再設計 → 再実装 ← 高コスト! 要件変更 = 高コスト の悪循環: ビジネスロジック変更 → UIも変更が必要 小さい単位での試行錯誤ができない UI完成しないと実際の操作フローが分からない 完成後に「やっぱりこの機能いらない」と判明… 前回の記事で触れた開発工数の差(16-24日 vs 数時間〜1日)の 本質的な理由がここにあります 。 ロジックファースト検証の発見 私の開発環境と、ロジックファースト検証の起源 以前、 AIチャットで話すだけ!X予約投稿を完全自動化するシステム構築術 で紹介したX予約投稿システムは、 Firestoreベース でした。 その後、データベースを Supabaseに移行 することになりました。そして移行時に、 ビジネスロジックの変更要求 が出てきたんです。 ここで悩みました: 従来の方法: UI設計 → フロントエンド実装 → ビジネスロジック検証 ↓ 問題: ビジネスロジックが固まっていないのにUIを作る? 検証してみたら要件変更 → UI作り直し? 「先にビジネスロジックを検証できないかな…」 そこで思いついたのが、 Claude CodeをUIとして使う 方法でした。UIを作らず、CLIツール + Skillsでビジネスロジックを先に検証してしまおう、と。 前回の記事で紹介した Supabase公式MCPを補完するSkills を実装し、こんな構成になりました: CLIツール(db コマンド) ↓ Skills定義(.claude/skills/*.md) ↓ Claude Codeから操作可能 特徴 : 基本CRUD操作のみ実装(posts, categories, hashtags, series) X投稿管理システムのデータベースを操作 UIは存在しない Claude Codeが「人間の操作UI」として機能 Skill運用開始後に起きた面白いこと 基本操作は順調でした: 私: 「投稿一覧を取得して」 Claude Code: uv run db posts list を実行 成功 私: 「カテゴリ一覧も見せて」 Claude Code: uv run db categories list を実行 成功 「Skill、便利だな!基本操作は完璧!」と思っていました。 しかし、 組み合わせ処理 を依頼すると、面白いことが起きました: 私のリクエスト : 「重複カテゴリを見つけてマージして」 Claude Codeの反応 : uv run db categories list を実行 カテゴリ一覧を取得 application/tools/tmp/merge_duplicate_categories.py を生成 ← ここ! スクリプトを実行して重複を検出 uv run db categories merge を実行 観察 : Skill(db)は基本操作のみ提供していました。組み合わせ処理のために、 Claude Codeが中間処理のスクリプトをtmp/に生成 していたんです。 「あれ、tmpにスクリプトが残ってる。これ、削除すべき?」 tmpの蓄積 1週間後、tmp/ディレクトリを覗いてみると: tmp/ ├── merge_duplicate_categories.py(3回生成) ├── validate_orphaned_posts.py(5回生成) ├── analyze_hashtag_stats.py(2回生成) ├── export_posts_csv.py(1回生成) └── bulk_update_scheduled_posts.py(4回生成) 「これ、ゴミじゃなくて何か意味があるのでは?」 同じスクリプトが複数回生成されている…これは偶然じゃない。 発見:tmpは「自然言語から生まれた要件」だ tmpの本質的価値 従来の認識 : tmp/ = 一時的なゴミ 実行後は削除すべき 気にしなくて良い 新しい認識 (私の発見): tmp/ = 人間の自然言語から生まれた純粋な要件の可視化 Skillの足りない機能の証拠 ビジネスロジックの暗黙知が形になったもの 次の改善のヒント なぜ「自然言語から生まれた要件」なのか? 理由1: 実際の利用パターンの記録 従来の要件定義プロセス : 人間が考える → 要件書に書く → 「こうあるべき」 → 抽象的、実際に使われるかは不明 ロジックファースト検証のプロセス : 人間が自然言語で依頼 → Claude Codeがtmpスクリプト生成 → 「実際にこう使った」 → 具体的、実証済み、検証済み 読者への問いかけ : あなたが書いた要件書、実際に全部使われましたか? 理由2: ビジネスルールの具現化 これが一番面白い発見でした。 要件書に書いたこと(抽象的) : 重複カテゴリを検出してマージできること tmp/merge_duplicate_categories.py の中身(具体的) : def find_duplicates(categories): """重複カテゴリを検出 重複の定義: 1. name完全一致 2. name.lower()一致(大文字小文字無視) 3. 編集距離が2以下(typo考慮) """ for i, cat1 in enumerate(categories): for cat2 in categories[i+1:]: similarity = SequenceMatcher( None, cat1["name"].lower(), cat2["name"].lower() ).ratio() if similarity > 0.9: # 90%以上の類似度 duplicates.append((cat1, cat2, similarity)) return duplicates def merge_strategy(duplicates): """マージ戦略 優先順位: 1. 投稿数が多い方を残す 2. created_atが古い方を残す 3. UUIDが辞書順で小さい方を残す """ # ... 実装 ... これが「人間の純粋な要件」です : 重複の具体的な定義(類似度90%以上) マージの優先順位(投稿数 > 作成日時 > UUID) エッジケースの扱い(複数重複がある場合) → 要件書には書かれていない詳細が、tmpスクリプトには全て含まれている 私が「重複カテゴリをマージして」と自然言語で依頼した時、頭の中にあった暗黙の要件が、tmpスクリプトとして可視化されたんです。 理由3: 組み合わせパターンの発見 Skill設計時の想定 : 基本CRUD操作のみ考えていた list, get, create, update, delete tmp/が教えてくれた実際の使い方 : list → 処理 → merge(組み合わせ) list → フィルタ → validate(検証) list → 集計 → sort(分析) → 実際の組み合わせパターンが自然に記録される Skill設計時には考えていなかった使い方が、tmpに全部記録されていました。 tmpに蓄積される3種類の情報 分析してみると、tmpスクリプトには3種類の情報が含まれていました: 基本操作の組み合わせパターン どのコマンドをどの順序で実行するか 例: db categories list → 処理 → db categories merge Skillにない独自ロジック 重複検索アルゴリズム(類似度計算) クロスチェック(複数テーブル横断) 統計・集計(Top10表示) ビジネスルールの実装 「重複とは何か」の具体的な定義 「孤立とは何か」の判断基準 「有用なハッシュタグ」の評価軸 tmpからビジネスロジックを抽出する 頻出パターンの観察 簡単な分析で、何が必要な機能かが見えてきました: # tmp/内のスクリプトを名前でカウント ls application/tools/tmp/*.py | xargs -n1 basename | sort | uniq -c | sort -nr 結果 : 5 validate_orphaned_posts.py 4 bulk_update_scheduled_posts.py 3 merge_duplicate_categories.py 2 analyze_hashtag_stats.py 1 export_posts_csv.py 解釈 : 5回生成 → 週1回以上使う → Skillに組み込むべき 3-4回 → 定期的に使う → Skill機能追加候補 1-2回 → tmpのままで良い(稀なケース) データが教えてくれました。「validate_orphaned_posts.pyは必要な機能だ」と。 ビジネスロジックの抽出事例 事例1: validate orphaned → Skill機能化 tmpの内容 (5回生成): # tmp/validate_orphaned_posts.py の処理フロー 1. uv run db posts list(全投稿取得) 2. カテゴリ未設定の投稿をフィルタ 3. 結果をリスト表示 発見 : 孤立投稿の検証は定期的に行う作業(週1回以上) ロジックが毎回同じ ビジネスルールが固まっている 「これ、毎回tmpスクリプト生成するの無駄じゃない?Skillに組み込もう」 Skillへの追加(Phase 3実装) : # 新しいコマンドとして実装 uv run db validate orphaned # 出力例 Orphaned Scheduled Posts: 0 Unused Categories: 2 ID: 106, Name: 本番環境構築 ID: 66, Name: フロントエンド Unused Hashtags: 1 ID: 34, Name: #TEST Total issues found: 3 → tmpスクリプトがSkillの本体機能に昇格 これで、次回から「孤立投稿を検証して」と依頼すると、tmpスクリプトを生成せず、直接Skill機能が実行されるようになりました。 事例2: 段階的な拡張プロセス tmp観察を続けることで、自然に機能が拡張されていきました: Phase 1(初期実装) : 基本CRUDのみ list, get, create, update, delete tmp観察(1週間) : カテゴリ・ハッシュタグでのフィルタ要求が頻出 統計情報の要求も多い Phase 2(拡張) : 複雑なクエリ追加 --category , --hashtag フィルタオプション stats コマンド(集計) 中間テーブル操作(add-categories, add-hashtags) tmp観察(さらに1週間) : merge系スクリプトが頻出 データクリーニングの需要が明確に Phase 3(さらに拡張) : データクリーニング機能 find-duplicates コマンド merge --dry-run コマンド validate orphaned コマンド → tmpの観察が、段階的な機能拡張を自然に導いた 段階的な開発により : 短期間でデータベース管理システムが完成(実測例として15時間程度) UIなしでビジネスロジックを整備できる理由 従来のUI先行開発 vs ロジックファースト検証 従来の方法 : 要件書「重複カテゴリをマージできること」 ↓ UI設計: ボタン、ダイアログ、進捗表示 ↓ フロントエンド実装(React等) ↓ 実際に使ってみる ↓ 「あれ、重複の定義が曖昧だった」 「マージ条件が足りない」 ↓ 仕様変更 → UI再設計 → 再実装 ← 高コスト! 問題 : ビジネスロジックが固まっていないのにUIを作っている ロジックファースト検証 : CLIツール(基本操作のみ) ↓ 人間が自然言語で依頼「重複カテゴリをマージして」 ↓ Claude Codeがtmp/merge_duplicate_categories.py を生成 ↓ tmpスクリプトに「重複の定義」「マージ戦略」が可視化される ↓ 頻出パターンを観察(週次レビュー) ↓ ビジネスロジック抽出 ↓ CLIに機能追加(`db categories find-duplicates`) ↓ ビジネスロジック完成(UIはまだない) ↓ 必要になったらUI実装(ロジック確定済み、手戻りなし) 利点 : ビジネスロジックを先に固められる UIなしで検証・改善できる 小さく試行錯誤できる UI設計時には要件が確定している → 手戻りゼロ Claude Codeが「操作UI」として機能 重要な洞察 : UIがないのではなく、 Claude Codeが人間の操作UIになっている 従来のUI: 人間 → Webフロントエンド → バックエンド → データベース ロジックファースト: 人間 → Claude Code(自然言語UI) → CLIツール → データベース なぜ「UI不要」が成立するのか – 概念的理解 従来のUIの役割を分解すると: 1. 視覚的フィードバック (操作結果の確認) 従来: ボタンを押して画面で結果を見る tmp駆動: tmpスクリプトを実行して、実行可能なフィードバックを得る 本質 : UIは「見るため」ではなく「確認するため」→ 実行結果で代替可能 2. 操作の抽象化 (複雑なコマンドを簡単に) 従来: ボタン一つで複雑な処理を実行 tmp駆動: 自然言語で依頼すると、Claude Codeがtmpスクリプト生成 本質 : UIは「操作を簡単にする」→ 自然言語で代替可能 3. 操作フローのガイド (次に何をすべきか示す) 従来: 画面遷移やメニューで操作を誘導 tmp駆動: tmpスクリプトの頻出パターンから次の機能を発見 本質 : UIは「発見を助ける」→ tmp観察で代替可能 つまり、 UIの役割は全て代替可能 です。 Claude CodeがUIとして優れている点 : 自然言語で操作できる(ボタン配置不要) 柔軟性が高い(固定画面レイアウトがない) 組み合わせ処理を即座に実行(カスタマイズ自在) tmpスクリプト生成で要件を可視化(暗黙知の顕在化) これが、フロントエンド開発をスキップできた理由です。 UI不要が適している場面・適さない場面 適している場面 : バックエンドロジック開発(データ処理、検証、変換) 自動化スクリプト(バッチ処理、CI/CD) インフラ管理(データベース操作、設定変更) 個人・小チーム利用(開発者のみが使う) UIが必要な場面 : ビジュアルデザインが重要(UI/UX設計が価値) 非エンジニアユーザー向け(自然言語UIでは不十分) リアルタイム性が重要(グラフ、ダッシュボード) 規制要件(監査証跡、操作履歴の可視化) 移行パターン : 多くの場合、こうなります: Phase 1: tmp駆動でロジック整備(UI不要) Phase 2: ロジック確定後、必要ならUI実装 UI実装は、 ロジックが固まってから 。手戻りがゼロになります。 将来的なアプリ化の価値 : ビジネスロジック検証で確定した機能は、 本当に人間が欲している機能 として証明されています。この段階でアプリ化すれば: 要件が固まっている → UI設計が明確 ビジネスルールが検証済み → 手戻りゼロ 実際の利用パターンが分かっている → 最適なUX設計が可能 tmpスクリプトの頻度から優先機能が明確 → 無駄な機能を作らない つまり、 tmpで検証したロジックをアプリ化することで、本当に価値のある機能だけを提供できる んです。 tmpがビジネスロジック整備を可能にする仕組み 1. 人間の暗黙知を可視化 → 「重複って何?」がtmpスクリプトに具体的な定義として現れる 2. 頻出パターンの発見 → 同じスクリプトが5回生成 → これは必要な機能だ 3. ビジネスルールの検証 → tmpスクリプトが実際に動く → ロジックが検証済み 4. UIなしで改善サイクル → tmp観察 → CLI拡張 → 再びtmp観察 → さらに拡張 この4つのステップが、UIなしでビジネスロジックを整備できる仕組みです。 まとめ tmpの再定義 従来の認識 : tmp/ = 一時的なゴミ 実行後は削除すべき 新しい理解 : tmp/ = 人間の自然言語から生まれた純粋な要件 ビジネスロジック整備の記録 UI設計のヒント tmpが実現する新しい開発フロー 従来: 要件定義 → UI設計 → 実装 → 「仕様変更...」 ロジックファースト: CLI基本実装 → Skill定義 → tmp蓄積 → ビジネスロジック抽出 → CLI拡張 → ロジック確定 → (必要なら)UI実装 革新的な点 : UIなしでビジネスロジックを整備・検証できる tmpが要件定義のプロセス自体を変える 小さく試行錯誤しながらロジックを固められる UI設計は後回し(ロジック確定後)→ 無駄なし 前回の記事の「短時間完成」の本当の意味 前回の記事で語ったこと : フロントエンド開発をスキップして短時間で完成(事実) 本記事で明かしたこと : tmpがビジネスロジックを整備してくれた(理由) なぜスキップできたのか : tmpがビジネスロジックを整備してくれた(自然言語から要件が生まれる) Claude Codeが人間の操作UIとして機能(Webフロントエンドが不要) UIは後回しにできる(ロジック確定後 → 手戻りなし) 開発プロセスの比較 : 従来: 要件定義(抽象的)→ UI設計 → フロント実装 → バックエンド 合計: 16-24日(128-192時間、一般的な工数見積として参考) ロジックファースト: CLI基本実装 → Skill定義 → tmp蓄積・観察 → CLI拡張 合計: 数時間〜1日(実測例として参考) 削減効果: UI開発をスキップすることで大幅削減 時間内訳の詳細 : フェーズ 従来 ロジックファースト 削減内容 要件定義 16-24h 最小限 大部分スキップ UI設計 32-48h 0h 100%削減 フロントエンド 40-60h 0h 100%削減 バックエンド 24-36h 数時間〜1日 大幅削減 機能拡張 16-24h 段階的に追加 柔軟に対応 削減の本質 : AIツールによる速度向上ではなく、 UI開発というアプローチ自体を変えた ことです。 核心的な発見 tmpスクリプトを観察することで: 人間の暗黙知が可視化される 「重複って何?」→ 類似度90%以上という具体的な定義 頻出パターンから優先順位が見える 5回生成 → 必要な機能 1回生成 → 稀なケース ビジネスルールが検証される tmpスクリプトが実際に動く → 検証済み UIなしで改善サイクルが回る tmp観察 → CLI拡張 → tmp観察 → さらに拡張 関連する開発手法との違い ロジックファースト検証は、既存の開発手法と何が違うのでしょうか? vs. 従来の仕様駆動開発 項目 仕様駆動開発 ロジックファースト検証 要件の形式 ドキュメント(抽象的) 実行可能スクリプト(具体的) 検証方法 レビュー会議 実行して確認 変更コスト 高い(ドキュメント更新 + 実装変更) 低い(tmpを捨てて再生成) 発見的開発 困難(仕様変更が重い) 容易(試行錯誤しやすい) 本質的な違い : ドキュメントは「こうあるべき」、tmpスクリプトは「実際にこう使った」 vs. AI駆動開発 項目 AI駆動開発 ロジックファースト検証 ツール依存性 高い(特定AIツールに依存) 低い(自然言語UIなら何でも) Skillsを使うならClaude依存 焦点 AIの活用方法 開発手法そのもの 適用範囲 コード生成中心 要件発見 → 実装まで 本質 ツール論 方法論 本質的な違い : AI駆動開発は「AIを使う」手法、ロジックファースト検証は「自然言語を要件にする」手法(ツール非依存) vs. TDD(テスト駆動開発) 項目 TDD ロジックファースト検証 駆動要素 テストコード tmpスクリプト 目的 品質保証 要件発見 成果物 永続的テスト 一時的スクリプト(昇格可能) サイクル Red → Green → Refactor tmp生成 → 観察 → 抽出 → 昇格 本質的な違い : TDDは「正しさ」を駆動、ロジックファースト検証は「要件そのもの」を駆動 ロジックファースト検証の位置づけ 要件発見フェーズ: ロジックファースト検証 ← 本手法の焦点 ↓ 実装フェーズ: TDD, AI駆動開発など ↓ 運用フェーズ: DevOps, SRE ロジックファースト検証は、 要件が固まっていない初期段階 に特に有効です。要件が明確になれば、TDDやAI駆動開発と組み合わせて使えます。 実践方法について tmpの具体的な観察方法、ビジネスロジックの抽出手順、環境セットアップなどの詳細は、次回の記事「 Claude Code一時ファイルからSkillsへ:ビジネスロジック抽出の実践ガイド 」で解説します。 次回の記事では: tmpディレクトリのプロジェクト内設定方法 週次レビューの実践 ビジネスロジック抽出の具体例(コード付き) 環境セットアップ(Python/uv, TypeScript) tmpからCLI機能への昇格プロセス を扱う予定です。 皆さんも、tmpスクリプトを削除せず、観察してみてください。そこには、 あなたの本当の要件が隠れています 。 参考リンク 公式ドキュメント Claude Code 公式ドキュメント Claude Code Skills 公式ガイド Supabase 公式ドキュメント Python 公式ドキュメント – 型ヒント、subprocess等 uv 公式ドキュメント 前提記事 Claude Code: 公式MCPを補完するSkills設計パターン 4層構造パターン(公式SDK → 自作Client → CLI → Skill) UI開発工数の大幅削減 なぜフロントエンド開発をスキップできたか(表面的な説明) 関連ブログ Claude Code Skills 実装ガイド:ローカルツールをスムーズに統合する方法 Skillの実装方法(詳細) Progressive Disclosure、トークン効率化 本記事の基盤となるSkills実装 HTMLでブログ記事を保存してる奴、全員Markdownにしろ。AIが読みにくいでしょうが! blog-scraperの実装例(tmpから進化したツール) トークン削減の実測データ AIチャットで話すだけ!X予約投稿を完全自動化するシステム構築術 X投稿管理システムの全体像 Azure Functions + Supabaseでの予約投稿自動化 次に読むべき記事 Claude Code一時ファイルからSkillsへ:ビジネスロジック抽出の実践ガイド : tmpの観察方法、ビジネスロジック抽出の具体例、環境セットアップを詳解 次回の記事では、本記事で説明した概念を実際にどう実装するかを、コード例を交えて解説します。 質問や感想は、コメント欄でお待ちしております! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Claude Codeの一時ファイルでビジネスロジック検証:UI不要で要件を発見する方法 first appeared on SIOS Tech. Lab .
アバター
はじめに ども!Claude Codeにべったりな龍ちゃんです。 2025年、Claude CodeのMCP対応が進み、GitHub、Slack、Supabase、Firebase等、多くのサービスで 公式MCPサーバー が利用可能になりました。 しかし実際のプロジェクトでは、 公式MCPだけでは不十分なケース が多々あります: カスタムビジネスロジック : 重複検出、データ検証、複数テーブル統合、マイグレーション処理 トークン最適化 : MCPは4サーバーで55.7k (27.9%)消費(※1) 独自要件 : 社内システム固有の処理、セキュリティ要件 本記事では、 公式MCPを基盤として、不足部分をSkillsで補完する 汎用的なパターンを、Supabaseの実例(700行Skill、30+コマンド)で解説します。しかも、 フロントエンド開発を一切スキップ して実現できました。 ※1: 実測データによると、MCPサーバーは大量のトークンを消費する傾向があります。 よく使ってたMCPはNotionだったんですけど、こいつトークンバカ食いするんですよね。 普通、カスタムビジネスロジックを人間が使えるようにしようと思ったら、Reactでフロントエンド開発して、デザインシステム作って、UX設計して…って、2〜3週間は覚悟しますよね?(AIを活用することで開発の工数を抑えてもそれでも大変!) でも、こう考えれば良いと気づいたんです: 公式SDK/APIをラップして自作Clientを作成 (カスタムビジネスロジック実装) 自作ClientをCLIツールでラップ CLIツールの使い方をSkillsとして定義 Claude Codeが「UIとして機能」する この汎用的なパターンを使えば、公式MCPで不十分な場合でも、カスタムビジネスロジックをClaude Codeと統合できます。 Supabase、Firebase、社内API等…全て同じ4層構造(公式SDK → 自作Client → CLI → Skill)のアプローチです。この発想で、全てが変わりました。 TL;DR この記事で分かること: 公式MCPを補完する3つのユースケース (2025年版) カスタムビジネスロジック : 重複検出、データ検証、複数テーブル統合(700行Skillの実例) トークン最適化 : MCP 55.7k (27.9%) vs Skills Progressive Disclosure 独自要件 : 社内システム、セキュリティ要件、レガシーシステム 汎用的な補完パターン : 公式SDK → 自作Client → CLI → Skill の4層構造 対象 : 公式MCPでカバーされないカスタムロジック 実装例 : Supabase(公式MCP + 700行Skill) 利用者数による技術選択 の判断基準 社内共有レベル: アプリ化(Streamable HTTP/WebSocket + Function Calling/MCP自作) 個人〜チーム: Claude Code + Skills 実装パターン : 短時間で完成 Step 1: カスタムビジネスロジックを自作Clientに実装 Step 2: CLI化(Click等) Step 3: Skill登録(Markdown) アプリ化をスキップ することで工数を大幅削減 アプリ化(一般的見積): 128-192時間(16-24日) Skills化(実測例): 数時間〜1日 削減の理由 : UI開発をスキップし、Claude Codeを操作インターフェースとして活用 MCP vs Skillの判断基準 を実例で解説 重要な前提条件: 対象サービスのAPI/SDKが存在する Python等のプログラミング基本知識 Claude Codeの基本操作を理解している こんな人に読んでほしい 公式MCPでは不十分なカスタムビジネスロジック を実装したい開発者 データ検証、重複検出、複数テーブル統合 等の独自処理が必要な人 社内APIやレガシーシステム をClaude Code対応したい開発者 MCPのトークン消費を最適化 したい人(4サーバーで27.9%消費に悩んでいる) 個人〜チームレベル でツールを使いたい人(大規模なアプリ化は不要) ビジネスロジックが固まっていない段階で、 小さく検証しながら開発 したい人 リモートMCP vs 自作MCP vs Skillで迷っている人 公式MCPをSkillsで補完する汎用パターンの発見 ある日、私はこんな課題に直面しました: 課題 : Supabaseに 公式MCPサーバーが存在する が、カスタムビジネスロジック(重複検出、データ検証、複数テーブル統合)は提供されない でも、フロントエンド開発で専用UIを作るのは時間がかかりすぎる 自作MCPサーバーを立てるのもインフラ管理が面倒 まず確認すべきこと(2025年版) : 公式MCPサーバーで十分か? GitHub、Slack、Notion、Supabase、Firebase等は公開MCPサーバーが存在 → 基本操作なら公式MCP使用(2024年11月のMCP発表以降、リモートMCPサーバーが順次展開) 参考: MCP Servers Directory 公式MCPで不十分な場合 : カスタムビジネスロジック : 重複検出、データ検証、複数テーブル統合、マイグレーション トークン最適化 : MCP 4サーバーで55.7k (27.9%)消費を回避したい 独自要件 : 社内API、レガシーシステム、セキュリティ要件 → 本記事の汎用パターン(Skillsで補完) 発見した汎用パターン (公式MCPを補完する場合): 公式SDK/APIをラップして自作Clientを作成 (カスタムビジネスロジック実装) 自作ClientをCLIツールでラップ Skillsとして使い方を定義 → この3ステップで公式MCPを補完し、カスタムロジックをClaude Codeと統合可能 今回の実例:Supabase公式MCPを700行Skillで補完 : 公式Supabase MCPでは提供されないカスタムロジックを実装 Supabase Python SDK(公式)をラップして自作Supabase Clientを作成 重複検出(find-duplicates)、データマイグレーション(merge –dry-run)、統計分析(stats)等を実装 別プロジェクトでの知見を活かして関数ベースのインターフェースで実装 自作ClientをCLIツールでラップ Skillsとして提供(700行、30+コマンド) フロントエンド開発なし MCPサーバー構築なし 短時間で運用開始 読者への問いかけ : あなたが実装したいカスタムビジネスロジック、ありませんか?この汎用パターンなら、公式MCPを補完できます。 システム利用者による技術選択 さて、外部サービスやシステムに人間がアクセスできるようにするには、どんな選択肢があるでしょうか? これは、Supabaseだけでなく、GitHub、Slack、AWS、社内API…あらゆるサービスとの接続で共通する判断です。 選択肢A:利用者が複数(社内共有レベル)→ アプリ化 想定シナリオ : 複数チームで使う、社内の共通ツールにする 技術スタック : フロントエンド:React等でWebアプリ開発 バックエンド:Streamable HTTP/WebSocket + Function Calling or MCP デプロイ:Azure/AWS等 ※MCP仕様では2025年3月にSSEトランスポートが非推奨化され、Streamable HTTPに置き換えられました。 開発工数(一般的な見積もり) : 16-24日(128-192時間) ※フルスタックWebアプリケーション開発(React + MCP統合)の一般的な工数。プロジェクトの複雑性により変動します。 要件定義: 2-3日 UI設計・フロントエンド開発: 10-13日(デザインシステム構築含む) バックエンド統合: 2-3日 テスト・デバッグ: 2-3日 問題点 : 時間がかかる : 16-24日の開発期間 柔軟性がない : UIを作った後のビジネスロジック変更が大変 ビジネスロジックを変更 → UIも変更 → 再設計・再実装 小さい単位での試行錯誤ができない 使いながら要件を整理する、ということができない 選択肢B:利用者が個人〜チーム → 小さいワークフロー 想定シナリオ : 自分だけ、またはチーム内での共有(Skillsファイル共有) 技術スタック : CLI:Click等でコマンドラインツール作成 Skills:Claude Code Skillsで使い方を定義 共有: .claude/skills/ ディレクトリを共有 開発工数 : 数時間〜1日 利点 : 即座に使い始められる ビジネスロジックだけを柔軟に変更 できる 小さく試行錯誤、使いながら要件を整理 判断:個人開発 → Skills採用 私の状況はこうでした: 判断基準 : 利用者: 自分だけ 要件: まだ固まっていない (使いながら整理したい) ビジネスロジック: 頻繁に変更 する可能性 デモ:操作を見せたいが、フロントエンド開発は避けたい → 選択肢B(Claude Code + Skills)を採用 特に、 ビジネスロジックが固まっていない段階でUIに投資するリスク を避けたかったんです。 さらなる選択:公式MCP vs 自作MCP vs Skill 選択肢B(Claude Code + ワークフロー)の中でも、実は技術選択肢が 3つ あります(2025年版): 公式MCP (Remote MCP) : 既存の公開MCPサーバーを利用(2024年11月〜順次展開) 自作MCP (Model Context Protocol) : 自分でMCPサーバーを実装 Skill : Claude Code専用のツール統合(Markdownファイル) 公式MCPサーバーが存在し、基本操作で十分な場合は、公式MCPが最も簡単です。 本記事のパターンは、公式MCPで不十分な場合(カスタムビジネスロジック、トークン最適化等)の選択です。 比較表(2025年版) 項目 公式MCP 自作MCP Skill 前提条件 公開MCPサーバーが存在 MCPサーバーを自作 公式MCPで不十分 or MCPが存在しない 実装難易度 最低(OAuth認証のみ) 高(Pythonライブラリ、サーバー起動) 低(Markdown 1ファイル) 学習コスト 最低 高 低 所要時間 数分 1-2日 数時間 対応環境 Claude Desktop統合 Claude Desktop統合 Claude Code専用 型安全性 高 高 – デバッグ 易 難 易 適用範囲 公開MCPがあるサービスの基本操作 外部システム連携 カスタムビジネスロジック、プロジェクト固有ツール 運用コスト $0(リモート) 高(サーバー稼働) $0(ローカル) トークン消費 多い(※) 多い(※) 少ない(Progressive Disclosure) (※)MCPのトークン消費問題 : 4つのMCPサーバーで 55.7k トークン(27.9%) 消費という実測例が報告されています。1つのMCPサーバーにつき10-20個のツール定義があるが、実際に使うのは1-2個だけという無駄が発生します。SkillsはProgressive Disclosure(段階的開示)により、この問題を回避できます。起動時にスキルの名前と説明のみを読み込み、必要に応じて完全な内容を段階的にロードします。 判断プロセス(2025年版) ステップ1: 公式MCPサーバーの確認 → Supabase公式MCPサーバーが存在(https://mcp.supabase.com/mcp)、基本CRUDは対応可能 ステップ2: 公式MCPで十分か? → カスタムロジック(find-duplicates、merge –dry-run、stats、validate)は公式MCPにない → 不十分 ステップ3: 自作MCP vs Skill → 使用者1人、ビジネスロジック検証、スピード重視、運用コスト$0 → Skill採用 実装例:Supabase公式MCPを補完【700行、30+コマンド】 それでは、公式MCPを補完する汎用パターンを具体例で見てみましょう。 今回の実装対象 : Supabase(公式MCP + カスタムビジネスロジック) 所要時間 : 数時間〜1日(実測値の一例として参考) 公式MCPの状況 : 基本CRUD操作は公式MCPサーバー(https://mcp.supabase.com/mcp)で対応可能 Skillで補完する内容 : 重複検出(find-duplicates)、データマイグレーション(merge –dry-run)、統計分析(stats)、整合性チェック(validate)等 成果物 : 5テーブル、30+コマンド、約700行Skill 汎用的な実装アプローチ(3ステップ) Step 1: 自作ServiceClient作成 公式SDK/APIをラップして、カスタムビジネスロジックを実装 例: Supabase Python SDK → 自作Supabase Client(重複検出、統計分析等) 他サービス: PyGitHub/slack-sdk/boto3等をラップ Step 2: CLI作成 自作ClientをClick等でCLIツール化 例: db posts list 、 db hashtags merge --to ID --from IDs レイヤー構造: Skill → CLI → 自作Client → 公式SDK → 外部サービス Step 3: Skill登録 Markdownファイルでコマンド使用方法を定義 Progressive Disclosure(段階的開示)で効率化:起動時にスキル名と説明のみ読み込み 例: .claude/skills/x-posts-manager.md (700行) なぜClientレイヤーを作るのか? 公式SDKを直接使わず、自作Clientを挟むことで: カスタムビジネスロジックをカプセル化 プロジェクト固有の処理を統一的に管理 関数ベースのインターフェース等の独自実装を追加可能 詳しい実装方法 は、 Claude Code Skills 実装ガイド を参照してください。 成果:UI開発工数の大幅削減 選択肢A vs 選択肢Bを比較してみましょう。 選択肢A:アプリ化(社内共有レベル)- 一般的な工数 要件定義(2-3日) → UI設計(3-5日) → フロントエンド開発(7-10日) → バックエンド統合(2-3日) → テスト(2-3日) └─────────────── 16-24日(128-192時間) ──────────────┘ ※フルスタックWebアプリケーション開発の一般的な工数見積もり 選択肢B:Skills化(個人〜チーム)- 実測例 CLI実装 → Skill化 → テスト └──────── 数時間〜1日 ────────┘ ※プロジェクトの複雑性により変動。Supabaseプロジェクトでは約8時間(1日)の実測例あり 削減効果の比較 項目 選択肢A(アプリ化)※一般的見積 選択肢B(Skills化)※実測例 削減内容 開発時間 128-192時間 数時間〜1日 UI開発をスキップ 工数 16-24人日 0.5-1人日 大幅削減 フロントエンド開発 7-10日 0日 スキップ UI設計 3-5日 0日 スキップ 運用開始 16-24日後 即日〜1日 迅速な立ち上げ 削減の理由: React等のフロントエンド開発をスキップ デザインシステム構築が不要 UX設計・テストが不要 Claude Codeが「人間が使うUI」として機能 得られた柔軟性: ビジネスロジックだけを変更できる(UIの再設計不要) 小さい単位で試行錯誤できる 使いながら要件を整理できる 重要: この削減は「AIツールによる開発速度向上」ではなく、 「UI開発というアプローチ自体を変えたこと」 による効果です。 フロントエンド開発をスキップして、短時間で運用開始できるんです。そして、後から自由に改善できる柔軟性も手に入れました。 汎用性:公式MCPを補完する展開 この汎用パターンの最大の価値は、 公式MCPが存在するサービスでも、カスタムビジネスロジックで補完できる ことです。 補完パターンの適用例 公開MCPが存在するサービス (カスタムロジックで補完): Supabase : 基本CRUD(公式MCP)+ 重複検出・統計分析・整合性チェック(Skill) Firebase : Firestore基本操作(公式MCP)+ 複数コレクション横断・セキュリティルール検証(Skill) GitHub : Issue/PR操作(公式MCP)+ カスタムラベル付け・複数リポジトリ横断分析(Skill) Slack : メッセージ送信(公式MCP)+ メッセージ集計分析・カスタム通知ロジック(Skill) 公開MCPが存在しないサービス (Skillで全て実装): 社内API、レガシーシステム、管理ツール、独自開発サービス 補完が必要な4つの理由 : カスタムビジネスロジック(公式MCPで提供されない独自処理) トークン最適化(MCP 55.7k消費を回避) セキュリティ要件(社内ネットワーク内でのみ動作) 小さく検証(ビジネスロジック固まっていない段階での試行錯誤) 参考 : MCP Servers Directory で公式MCPサーバーの有無を確認できます 実装パターンは全て同じ どのサービスでも: 公式SDK/APIをラップ → 自作ServiceClient作成(ビジネスロジック実装) CLI化 → 自作ClientをClick等でラップ Skill登録 → Markdownで使い方定義 → Claude Codeから操作可能に レイヤー構造の利点 : 公式SDK : サービス通信の実装を提供(変更不要) 自作Client : プロジェクト固有のビジネスロジックを実装 CLI : コマンドラインインターフェースを提供 Skill : Claude Codeとの統合を提供 フロントエンド開発をスキップしつつ、あらゆるサービスをClaude Code経由で操作できるようになります。しかも、自作Clientレイヤーでビジネスロジックをカプセル化できるため、柔軟性も高いです。これは、個人開発〜チームレベルの開発において、強力なアプローチです。 まとめ 今回は、 公式MCPを補完するSkills活用パターン を紹介しました。 核心的な発見 2025年版の判断フロー : 公式MCPで十分か確認 → 基本操作なら公式MCP使用(最も簡単) 公式MCPで不十分な場合 → 本記事の補完パターン(Skillsで拡張) 3つの補完ユースケース : カスタムビジネスロジック : 重複検出、データ検証、複数テーブル統合 トークン最適化 : MCP 55.7k (27.9%)消費を回避 独自要件 : 社内システム、セキュリティ要件 汎用的な補完パターン : 公式SDK → 自作Client → CLI → Skill の4層構造 レイヤーの役割 : 公式SDK: サービス通信を提供 自作Client: カスタムビジネスロジックをカプセル化(関数ベースのインターフェース等) CLI: コマンドラインインターフェース提供 Skill: Claude Code統合、Progressive Disclosure(段階的開示) 実装例(Supabase) : 公式MCP + 700行Skill、フロントエンド開発なし 公式MCP: 基本CRUD操作 Skill: find-duplicates、merge –dry-run、stats、validate等 実装時間: 数時間〜1日(実測例として参考) Skillの優位性 : Progressive Disclosure(段階的開示)により トークン消費を大幅削減 (MCP: 55.7k vs Skill: 起動時は名前と説明のみ) 運用コスト $0(ローカル完結) 実装時間 数時間〜1日(自作MCP: 1-2日) UI開発工数削減 : アプリ化(一般的見積: 128-192時間)→ Skills化(実測例: 数時間〜1日) 柔軟性 : UIがないので、ビジネスロジックだけを小さく検証・変更できる 既存ブログとの違い 以前書いた Claude Code Skills 実装ガイド では、「 Skillの作り方(How to) 」を解説しました。 今回は、 「公式MCPを補完する汎用パターン(What you can achieve)」 と 「Skillに至った経緯(Why & 判断プロセス)」 を中心に語りました。 今すぐできること 実装したいカスタムビジネスロジックを明確にする : 重複検出、データ検証、複数テーブル統合、統計分析…等 公式MCPサーバーの有無と機能を確認 : MCP Servers Directory で検索 公式MCPで十分 → 公式MCP使用(最も簡単) 公式MCPで不十分 → 次のステップへ(カスタムロジック補完) MCPがない → 次のステップへ(全て実装) SDK/APIを確認 : 対象サービスのPython SDK、REST APIドキュメントをチェック 4層構造で実装 (数時間〜1日目安): 公式SDK : 既存のライブラリを利用(Supabase SDK、firebase-admin等) 自作Client : 公式SDKをラップしてカスタムビジネスロジック実装 CLI : 自作ClientをClickでラップ Skill : Markdownで使い方定義(Progressive Disclosure対応) 公式MCP vs 自作MCP vs Skillで迷っている人 : この記事の判断フローを参考に フロントエンド開発を避けたい人 : Skills化で即座に運用開始 この汎用パターンを覚えておけば、公式MCPを補完し、カスタムビジネスロジックをClaude Codeと統合できます。 皆さんも、実装したいカスタムロジックがあったら、まず公式MCPサーバーの有無と機能を確認し、不十分ならこの補完パターンを試してみてください! 参考リンク 公式ドキュメント Claude Code 公式ドキュメント MCP (Model Context Protocol) 公式ドキュメント MCP Servers Directory – 公式MCPサーバー一覧 Anthropic Skills 公式発表 Supabase 公式ドキュメント Supabase MCP Server Python Click 公式ドキュメント – CLIツール作成ライブラリ uv 公式ドキュメント – Pythonパッケージマネージャー 関連ブログ Claude Code Skills 実装ガイド:ローカルツールをスムーズに統合する方法 本記事で説明した「Skill化」の詳細実装方法 Skillファイルの構造、YAML frontmatter、ベストプラクティス 【2025年版】検証 → 記事化で知見を資産化!Claude Code×RAGもどきでAI技術ブログ執筆を効率化 「RAGもどき」のアイデアの原点 Claude Codeを活用したブログ執筆ワークフロー AI協業開発環境の構築術|モノレポでビルド時間を大幅短縮するCLAUDE.md活用法 開発環境のセットアップ(モノレポ、uv、devcontainer) 本記事のプロジェクト構成の基礎 質問や感想は、コメント欄でお待ちしております! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Claude Code: 公式MCPを補完するSkills設計パターン first appeared on SIOS Tech. Lab .
アバター
はじめに ども!Claude Code を執筆に贅沢活用している龍ちゃんです。 前回の SVG図解自動生成記事 で、「SVGで図解作成時間を67%削減できた!」って話をしたんですが、正直に言うと 完璧ではなかった んですよね。 フロントエンドエンジニアとしてTailwind CSSを日常的に使っている僕からすると、 あとから編集もできちゃうんですよね 。ClaudeもTailwindが得意なので、SVGを作るよりHTML経由で図を作ってスクショする方が、PNG変換という手間は増えるんですけど、意図した図が作れるんです。 HTMLで図解を作る利点 1. レイアウトが一発で決まる ClaudeはCSS(特にFlexbox/Grid)が得意なので、paddingや文字の設定、レイアウトの統一感がSVGより圧倒的に実現しやすいです。 Claudeで作るSVGと比較すると、レイアウト崩れが基本的になくなります。 2. コードが読める人なら編集・活用が簡単 HTMLを読んで図を修正したり活用したりできるのは利点ですね。Material IconsもSVGと同じように使えるし、個人的にTailwind CSSが好き(入社した時に初めて学んだ技術)っていうのもあります。 3. Figmaで編集可能 HTMLをSVGに変換する便利なライブラリーが出てきているので、Figmaで後から編集することもできます。 4. PNG変換の選択肢が豊富 Playwright(MCP/Pythonパッケージ)やhtml2imageなどのライブラリーを使って、HTMLからPNG画像を生成できます。 今回のブログの対象範囲 今回は HTMLで図解を作るところまで を対象としています。PNG変換については後半で軽く触れますが、詳細は別記事で扱う予定です。 理想としてはWordPressサイトに直接HTMLを挟み込むこともありなんですけど、動作が重くなるので、まあご愛嬌かなと(笑)。 一番簡単な方法としてはブラウザで立ち上げてスクショですね。 試してみて感じたこと 驚くほど簡単でした。 SVGでは頻繁に発生していた微調整が、今回試したHTML図解3つは全て修正不要で完成しました。 今後、僕がブログで図を作るなら : まずMermaidでできないか考える 無理ならHTMLで作る という手段になりますね。 ベストプラクティスを一緒に模索しましょう Skillの共有は今回もGistで提供しています。ベースはSVGでやってた方法とほぼ一緒で、Claudeに調査してもらって、レイアウトの比率やHTML用にカスタムしたルールを追加している段階です。 Note : HTML 図解生成 Skill の完全版は Gist で公開中 Skill の作り方について詳しくは Claude Code Skillの登録と実践! を参照してください 高機能な図を作るためのベストプラクティス、僕も模索中です。 もし「いい方法があるよ!」「これやってないの?」みたいなツッコミがあれば、ぜひXの方でDMください。 @SIOSTechLab でも @RyuReina_Tech でもどちらでも大歓迎です! この記事で伝えたいこと SVGとHTMLを使い分けることで、より柔軟な図解作成が可能になります。 この記事で扱う内容 : HTML + Tailwind CSS 図解自動生成 Skillの実装 SVGで遭遇した問題の解決方法 (重要!) SVGとHTMLの使い分けガイドライン PNG変換ワークフロー SVG記事で遭遇した課題とHTMLでの解決 課題 SVGでの状況 HTML + Tailwind CSSでの解決 文字列のはみ出し font-size調整が必要(頻繁に発生) text-center , p-4 で自動余白確保 要素の重なり padding調整が必要(頻繁に発生) Flexboxの gap-6 で自動間隔確保 カスタム矢印問題 Material Icons推奨でも無視されることがある <span class="material-symbols-outlined">arrow_downward</span> 配置のバラつき 座標計算ミスが発生 Gridレイアウトで均等配置が自動 結論 : レイアウト自動化で座標計算から解放されました。 HTML図解自動生成 Skillの実装 Skillファイルの構成 .claude/skills/diagram-generator-html.md を作成し、以下の要素を含めます: 主要な指示内容 : Tailwind CSS CDN使用 (レイアウトを簡単に) 注 : CDNは開発・プロトタイプ用です。PNG変換後は静的画像になるため、本番環境の制限は適用されません Material Symbols Outlined (クラス指定だけでアイコン使用) 固定サイズ : 1280 x 720 px (16:9) アクセシビリティ対応 ( role="img" , aria-label ) 実装のポイント 1. Tailwind CSSで統一されたレイアウト <div class="flex flex-col gap-6"> <!-- 自動的に縦方向に6の間隔で配置 --> </div> ポイント : 座標計算不要。 gap-6 だけで要素間隔が自動確保されます。 2. Material Iconsがクラス指定だけで使える <span class="material-symbols-outlined text-6xl text-blue-600">database</span> SVGとの比較 : SVG: <path d="M12,3C7.58..." fill="#2196F3"/> を手動で埋め込む HTML: クラス名を指定するだけ 3. 固定サイズで一貫性を保つ <body class="w-[1280px] h-[720px] m-0 p-0"> ポイント : PNG変換時に正確なサイズが保証されます。 実際に使ってみた 使い方の流れ Claude Codeに「HTMLで○○の図を作って」と依頼 Skillが自動起動 不足情報があれば質問される HTMLファイルが生成される PNGファイルとして docs/article/[feature-name]/images/ に保存 実例1: 3層アーキテクチャ図の生成 依頼内容 : HTMLで3層アーキテクチャの図を作ってください。 Presentation Layer、Business Logic Layer、Data Access Layerの構成です。 Material Iconsを使って、各層にアイコンを配置してください。 生成されたHTML (抜粋): <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>3層アーキテクチャ</title> <script src="https://cdn.tailwindcss.com"></script> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" /> </head> <body class="w-[1280px] h-[720px] m-0 p-0"> <div class="w-full h-full bg-gray-50 flex items-center justify-center p-12"> <div class="w-full max-w-4xl flex flex-col gap-6"> <!-- Presentation Layer --> <div class="bg-blue-100 border-2 border-blue-500 rounded-lg p-6"> <div class="flex items-center justify-center gap-3"> <span class="material-symbols-outlined text-5xl text-blue-600">desktop_windows</span> <div class="text-center"> <h2 class="text-2xl font-bold text-blue-900">Presentation Layer</h2> <p class="text-lg text-blue-700 mt-1">UI・ユーザーインターフェース</p> </div> </div> </div> <!-- Arrow --> <div class="text-center"> <span class="material-symbols-outlined text-5xl text-gray-400">arrow_downward</span> </div> <!-- (他の層も同様) --> </div> </div> </body> </html> 結果 : ファイルサイズ: 43.74 KB(推奨範囲内) サイズ: 1280 x 720 px 修正不要 (一発で完成) ポイント : Flexboxの gap-6 で矢印との間隔が自動確保 Material Iconsがクラス指定だけで表示 文字列のはみ出しゼロ 実例2: ユーザー認証フロー図の生成 依頼内容 : HTMLでユーザー認証フローの図を作ってください。 開始 → 認証情報入力 → 検証 → セッション確立 → 完了の流れです。 開始と完了は楕円形、プロセスは矩形で表現してください。 生成されたHTML (抜粋): <div class="flex flex-col items-center gap-8"> <!-- 開始(楕円形) --> <div class="bg-green-100 border-2 border-green-500 rounded-full px-12 py-6"> <span class="text-xl font-bold text-green-900">開始</span> </div> <!-- 矢印 --> <div class="text-center"> <span class="text-4xl text-gray-400">↓</span> </div> <!-- 認証情報入力(矩形) --> <div class="bg-blue-100 border-2 border-blue-500 rounded-lg px-8 py-4"> <span class="text-lg font-semibold text-blue-900">認証情報入力</span> </div> <!-- (他のステップも同様) --> </div> 結果 : ファイルサイズ: 29.21 KB 修正不要 (一発で完成) ポイント : rounded-full で楕円形、 rounded-lg で矩形が簡単に実装 Unicode文字 ↓ でシンプルな矢印 中央揃え配置が自動 実例3: Before/After比較図の生成 依頼内容 : HTMLで図解作成の時短効果を比較するBefore/After図を作ってください。 Before(赤系): - 作業時間: 45分 - ツール: Figma / PowerPoint - 課題: 時間がかかる After(緑系): - 作業時間: 15分 - ツール: Claude Code Skill - 内訳: 生成5分 + 修正10分 - 効果: 67% 時短! 生成されたHTML (抜粋): <div class="grid grid-cols-2 gap-12"> <!-- Before --> <div class="bg-red-50 border-2 border-red-300 rounded-lg p-8"> <h3 class="text-2xl font-bold text-red-900 mb-4">Before(手動作成)</h3> <div class="space-y-3 text-red-800"> <p class="text-lg">⏱ 作業時間: <strong>45分</strong></p> <p class="text-lg">🛠 ツール: Figma / PowerPoint</p> <p class="text-lg">⚠ 課題: 時間がかかる</p> </div> </div> <!-- After --> <div class="bg-green-50 border-2 border-green-300 rounded-lg p-8"> <h3 class="text-2xl font-bold text-green-900 mb-4">After(Skill生成)</h3> <div class="space-y-3 text-green-800"> <p class="text-lg">⏱ 作業時間: <strong>15分</strong></p> <p class="text-lg">🛠 ツール: Claude Code Skill</p> <p class="text-lg">📊 内訳: 生成5分 + 修正10分</p> <div class="bg-green-100 border border-green-400 rounded px-3 py-1 mt-2 inline-block"> <span class="text-sm font-bold text-green-900">✨ 67% 時短!</span> </div> </div> </div> </div> 結果 : ファイルサイズ: 37.11 KB 修正不要 (一発で完成) ポイント : grid grid-cols-2 gap-12 で2カラムレイアウトが自動 配色統一(Before: 赤系、After: 緑系) 効果バッジも簡単に実装 SVG記事との比較 図解 SVG記事(修正の有無) HTML検証結果(修正の有無) 3層アーキテクチャ 修正が必要だった 修正不要 認証フロー 修正が必要だった 修正不要 Before/After 修正が必要だった 修正不要 結論 : 今回試した3つの実例では、全て修正不要で完成。SVGで遭遇した問題を解決できました。 Material Icons活用術 Googleが提供する2000種類以上の無料アイコン集が、HTMLなら クラス指定だけで使える のが最大の利点です。 使用方法 : <!-- CDN読み込み --> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" /> <!-- アイコン配置 --> <span class="material-symbols-outlined text-6xl text-blue-600">database</span> SVGとの比較 : 操作 SVG HTML 配置 パス手動埋め込み <span> タグでクラス指定 変更 パス全体差し替え 名前変更だけ( database → cloud_upload ) サイズ/色 属性調整 Tailwindクラス変更( text-6xl , text-blue-600 ) 結論 : HTMLの方が圧倒的に簡単。 SVGとHTMLの使い分けガイドライン 正直に言うと、 SVGとHTMLは適材適所 です。完璧なものは一発で作れませんが、使い分けることで効率化できます。 SVGを選ぶべきケース ベクター形式が必須 印刷物 高解像度ディスプレイ 拡大しても劣化させたくない ファイルサイズを最小化したい SVG: 2-5 KB PNG: 30-50 KB Figmaで後から編集する予定 SVGはFigmaで直接編集可能 複雑な図形を描く必要がある パスやベジェ曲線を使った図形 HTMLを選ぶべきケース シンプルなレイアウト 矩形、楕円形中心の図解 Flexbox/Gridで十分な場合 Tailwind CSSに慣れている クラス指定だけでスタイリング完了 Material Iconsを多用したい クラス指定だけで簡単実装 座標計算を避けたい レイアウトシステムで自動配置 修正の手間を最小化したい SVG: 頻繁に微調整が必要 HTML: 今回の3つの実例では全て修正不要 併用のすすめ プロトタイプ : HTML(速い、簡単) 図解のレイアウトを素早く確認 本番(ベクター重視) : SVG(品質高い) 印刷物や高解像度ディスプレイ向け 本番(レイアウト重視) : HTML(修正不要) ブログ埋め込み、SNS共有向け 実運用で遭遇する問題点と対処法 問題1: PNG変換が必須 問題 : HTMLファイル単体ではブログに埋め込めない(サイトによる) 対処法 : どうやってかPNGに変換(Playwright・スクショ・etc…) ワークフロー: HTML生成 → PNG変換 → ブログに埋め込み 問題2: Tailwind CDN依存 問題 : HTML生成時にインターネット接続が必要 対処法 : PNG変換時にChromiumが自動でCDNから取得 変換後はPNG画像なので、CDN不要 問題3: JavaScript/アニメーション禁止 問題 : 静的な図解のみ対応(インタラクティブ要素は不可) 対処法 : 静的な図解に用途を限定 インタラクティブな図解が必要なら別のアプローチを検討 SVG記事と比較して「発生しなかった」問題 文字列幅の不一致 : Tailwindの自動余白で解決 要素の重なり : Flexbox/Gridの gap で解決 カスタム矢印問題 : Material Iconsのクラス指定で解決 配置のバラつき : レイアウトシステムで解決 アクセシビリティ対応 WCAG Level AA準拠 コントラスト比 4.5:1以上の自動適用とスクリーンリーダー対応を実装しています。 実装例 : <div class="w-full h-full bg-white flex items-center justify-center" role="img" aria-label="3層アーキテクチャ図"> <!-- 図解の内容 --> </div> Tailwindでのコントラスト確保 用途 Tailwind Class コントラスト比 Primary bg-blue-500 , text-blue-900 4.5:1以上 Secondary bg-green-500 , text-green-900 4.5:1以上 Accent bg-orange-500 , text-orange-900 4.5:1以上 まとめ:SVGとHTMLを使い分けて効率化 HTML図解生成の評価 良い点 : レイアウトが簡単(Flexbox/Grid) 修正の必要性が低い(10-20%) Material Iconsが簡単(クラス指定だけ) 配色の統一が容易(Tailwind) 課題 : PNG変換が必須 ファイルサイズがやや大きい(30-50 KB) ベクター形式ではない 時短効果の測定 今回試した3つの図解で、作成時間を計測しました: 作業 手動作成(想定時間) HTML Skill生成 削減時間 3層アーキテクチャ図 約45分 5分(修正なし) 約40分 ユーザー認証フロー図 約30分 4分(修正なし) 約26分 Before/After比較図 約60分 6分(修正なし) 約54分 全ての実例で修正作業が不要 だったため、大幅な時短を実現できました。 PNG変換について HTMLファイルはブログに直接埋め込めない場合があるため、PNG画像に変換して使用します。 今回はHTML図解の生成に焦点を当てているため、PNG変換の詳細は別記事で扱う予定です。簡単に触れておくと、ブラウザでの手動スクリーンショットやPlaywright/html2imageなどのライブラリーでHTMLからPNG画像を生成できます。 次のステップ 関連記事 : SVG図解自動生成記事 ClaudeでMermaid図作成を自動化!2時間→5分の劇的時短術【Live Editor活用】 今後の展開 : PNG変換の詳細(別記事予定) 画像最適化のベストプラクティス コード例:Skillファイルの抜粋 HTML 図解生成 Skill の完全版は Gist で公開中 --- name: diagram-generator-html description: 技術ブログ記事用のHTML図解を生成しPNG画像に変換するスキル。 allowed-tools: Read, Write, Bash --- # HTML Diagram Generator Skill 技術ブログ記事用のHTML図解を自動生成し、PNG画像に変換するSkillです。 ## When to Use 以下の場合にこのスキルを使用してください: - ユーザーが「HTMLで図を作って」と依頼した場合 - ユーザーが「Tailwindで図解を生成して」と依頼した場合 - SVGで座標計算が面倒な場合 ## Design Specifications ### 基本仕様 - **固定サイズ**: 1280 x 720 px (16:9) - **フォーマット**: HTML5 + Tailwind CSS - **最終出力**: PNG画像 ### Tailwind CSS活用 - **CDN**: `https://cdn.tailwindcss.com` - **レイアウト**: Flexbox/Gridで自動配置 - **配色**: `bg-blue-100`, `text-blue-900`など統一されたクラス ### Material Icons統合 - **フォント**: Material Symbols Outlined - **CDN**: `https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined` - **使用例**: `<span class="material-symbols-outlined">database</span>` ## Supported Design Patterns 1. **アーキテクチャ図**: レイヤード、マイクロサービス 2. **フロー図**: プロセス、データフロー 3. **関係図**: ER図、クラス図 4. **比較図**: Before/After、パフォーマンス比較 5. **コンポーネント図**: システム構成 6. **概念図**: コンセプトマップ ## HTML Template Example ```html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>図解タイトル</title> <script src="https://cdn.tailwindcss.com"></script> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" /> </head> <body class="w-[1280px] h-[720px] m-0 p-0"> <div class="w-full h-full bg-gray-50 flex items-center justify-center p-12" role="img" aria-label="図解の説明"> <!-- 図解の内容 --> </div> </body> </html> ``` ## Accessibility Requirements - **role属性**: `role="img"` - **aria-label**: 図解の内容を説明 - **コントラスト比**: WCAG Level AA準拠(4.5:1以上) ## Workflow 1. ユーザーからの依頼内容を確認 2. HTMLファイルを生成 3. `docs/article/[feature-name]/images/original/` に保存 4. `html-screenshot` CLIでPNG変換 5. `docs/article/[feature-name]/images/` にPNG保存 最後まで読んでいただき、ありがとうございました! この記事が役に立ったら、ぜひSNSでシェアしてください。質問やフィードバックは、 @RyuReina_Tech や @SIOSTechLab でお待ちしています! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Claude Code SkillでHTML図解を自動生成!時短テクニック first appeared on SIOS Tech. Lab .
アバター
はじめに ども!Claude Code を執筆に贅沢活用している龍ちゃんです。気づいたら3年でブログを200本書いていて、そろそろブログの本数をカウントするのを取りやめですね(笑)。 最近は週に5本くらいブログを書くことが習慣づいているんですが、これだけブログを書いてると、だんだん図を作るのが億劫になってしまうんですよね。Claude Code のおかげで Mermaid での図解作成はすごく短縮できました(参考: ClaudeでMermaid図作成を自動化!2時間→5分の劇的時短術【Live Editor活用】 )。 今月は社内でそういう環境を提供する活動を始めていまして、その過程で「今まで SVG で作ることを諦めていたけど、もうちょっと頑張ってみようかな」ってところでスキル化したりしてます。 正直に言うと、完璧に動くものはまだできてないんですよね。 でも、比較的質の高い図を作れるようになったので、その方法を共有します。 作ってみて感じたこと 完璧なものを一発で作ることは不可能 でした。ライトなブログなら そのまま使えますが、ちゃんとした図を作るなら Figma などの専用ツールが必要です。 それでも、 図解作成時間を67%削減 (45分 → 15分)できたので、方法と課題・解決策を共有します。 この記事で伝えたいこと 完璧なものは絶対一発で作れません。 でも、現状の Skill を共有するので、一緒にベストプラクティスを模索していきましょう! この記事で扱う内容 : SVG 図解自動生成 Skill の実装 実運用で遭遇した問題点と対処法 (重要!) Mermaid.js との使い分け Claude Code Skill とは? .claude/skills/ ディレクトリに Markdown 形式のプロンプトファイル を配置することで、Claude がタスクを自動実行できる機能です。 Skill のメリット : 一度作成すれば繰り返し使える キーワードで自動トリガー チーム全体で共有可能 Note : SVG 図解生成 Skill の完全版は Gist で公開中 Skill の作り方について詳しくは Claude Code Skillの登録と実践!プロジェクト固有の処理を自動化する方法 を参照してください SVG 図解自動生成 Skill の実装 なぜ SVG を選んだのか? 一番の理由はFigmaで後から人力編集できるって点ですね。 アプローチ 用途 Mermaid.js システム図(クラス図、シーケンス図)→ 高精度で素早く生成 SVG 直接生成 概念図、ビジュアル重視の図解 → デザインの完全制御が可能 HTML + CSS インタラクティブな図解 結論 : デザインの自由度とアクセシビリティを重視し、SVG 直接生成を選択しました。Mermaid だと無機質になるケースで SVG が活躍します。 図解デザインの基本原則 正直に言うと、僕はデザイナーではないのでデザインパターンやコントラストの知識はないんですよね。 そこで、いったん Claude に調査を依頼して、それを Skill に取り込むという手法を採用しています。 以下は Claude に調査させて得られたデザインパターンです: 1. C4 Model(階層化) Context : システム全体の概念図 Container : サービス間の相互作用 Component : 個別コンポーネントの詳細 Code : クラス図・シーケンス図(Mermaid が得意) 2. 60-30-10 ルール(色使い) 60%: 背景、30%: 矩形、10%: アクセント(矢印) 3. 視覚的ヒエラルキーの7原則 Size / Color / Contrast / Alignment / Repetition / Proximity / Whitespace(padding 50px の根拠) ポイント : デザインの専門知識がなくても、Claude に「効果的な図解デザインのベストプラクティスを調査して」と依頼すれば、これらの原則を教えてくれます。それを Skill のプロンプトに組み込むことで、質の高い図解が生成できるようになるんですよね。 Skill ファイルの構成 .claude/skills/diagram-generator-svg.md を作成し、以下の要素を含めます: 主要な指示内容 : Material Icons の統一使用 (desktop_windows、settings、storage など) WCAG Level AA 準拠 (コントラスト比 4.5:1) レイアウトガイドライン (padding 50px、font-size 16-32px) アクセシビリティ対応 ( <title> と <desc> 要素) SVG 図解生成 Skill の完全版は Gist で公開中 実装のポイント これだけ設定していてもがっつり無視してきたりするので、きれずに根気よく会話していきましょう。 1. Material Icons の統一使用 Skill のプロンプトで「Material Icons を使用」と指示しても、Claude は時々カスタム矢印( <path> + marker-end )を生成してしまいます。これを防ぐため、以下を明記: これを書いていても無視しますよww 3. **Layout Guidelines** - Arrows should use Material Icons (arrow_downward, arrow_forward) - DO NOT use custom `<marker>` or `<marker-end>` 2. アクセシビリティ対応 WCAG Level AA 準拠のため、コントラスト比を明示: 2. **Accessibility (WCAG Level AA)** - Color contrast ratio ≥ 4.5:1 - Text color on background must meet WCAG AA standards 3. 配置の明確化 要素間の余白を明示的に指定: - Use consistent spacing (50px padding between elements) - Text should not overflow rectangles 実運用で遭遇する問題点 ここからが重要です。実際に Skill を使ってみると、 プロンプト通りに生成されないことが多々あります 。以下、僕が実際に遭遇した問題と対処法です。 問題1: 文字列幅の不一致 症状 : 説明文(例: “UI・ユーザーインターフェース (React, Vue.js, Angular)”)が矩形からはみ出す 原因 : Claude が文字列の実際の表示幅を正確に計算できない 対処法 : <!-- Before: font-size="18" だと長い --> <text font-size="18">UI・ユーザーインターフェース (React, Vue.js, Angular)</text> <!-- After: font-size="16" に縮小 --> <text font-size="16">UI・ユーザーインターフェース (React, Vue.js, Angular)</text> 僕の場合、最初に生成されたSVGを見て「あ、これ文字はみ出てるな」って気づいたら、すぐにfont-sizeを調整するようにしています。 問題2: 要素の重なり 症状 : 矢印と矩形が重なって見える 原因 : padding が不十分(40px では足りない) 対処法 : <!-- Before: padding 40px --> <rect y="80" height="140"/> <g transform="translate(620, 220)"> <!-- 80 + 140 = 220 --> <!-- Arrow --> </g> <rect y="260" height="140"/> <!-- 220 + 40 = 260 --> <!-- After: padding 50px --> <rect y="80" height="140"/> <g transform="translate(620, 230)"> <!-- 80 + 140 + 10 = 230 --> <!-- Arrow --> </g> <rect y="270" height="140"/> <!-- 230 + 40 = 270 --> これは視認性の問題なんですが、40pxだと視覚的に「ちょっと詰まってるな」って感じがしたので、50pxにしたら見やすくなりました。 問題3: カスタム矢印の生成 症状 : Material Icons を指示しても、 <path> + marker-end のカスタム矢印を生成してしまう Claude が生成するコード(NG) : <!-- NG: カスタム矢印 --> <path d="M 640 220 L 640 260" stroke="#424242" stroke-width="3" marker-end="url(#arrowhead)"/> <defs> <marker id="arrowhead" markerWidth="10" markerHeight="10"> <polygon points="0 0, 10 5, 0 10" fill="#424242"/> </marker> </defs> 対処法 : Material Icons の arrow_downward を直接指定 <!-- OK: Material Icons --> <g transform="translate(620, 230)"> <path d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z" fill="#757575" transform="scale(1.5)"/> </g> これ、本当によくあるんですよね。プロンプトに明記してても無視されるので、生成後に手動で置き換えるのが確実です。 問題4: 配置のバラつき 症状 : 矩形の高さや幅、要素間の距離が統一されていない 対処法 : プロンプトで数値を明示 ## Layout Specifications - Rectangle width: 900px - Rectangle height: 140px - Padding between elements: 50px - Icon size: 48px (Material Icons scale(2)) - Arrow size: 36px (Material Icons scale(1.5)) 数値を具体的に指定しておくと、生成される図の一貫性が上がります。ただし、それでもズレることはあるので、最終的には目視確認が必要ですね。 修正ワークフロー 実際の図解作成は以下のフローで進めます: Skill で初回生成 (所要時間: 5分) プロンプトを渡して SVG を生成 構造は正しいが、細かい問題がある状態 手動修正 (所要時間: 10分) 文字列のはみ出しをチェック → font-size 調整 要素の重なりをチェック → padding 調整 カスタム矢印をチェック → Material Icons に置換 配置のバラつきをチェック → 数値を統一 ブラウザで確認 SVG ファイルを VScode で開いて視覚確認 問題があれば 2 に戻る 合計所要時間: 15分 (従来の45分から67%削減!) 僕の場合、Figmaで一から作ると構造を考えるところから始まって45分くらいかかってたんですが、Skillで構造を生成してもらえるだけで圧倒的に楽になりましたね。 生成例:Before → After 比較 実際の図解生成プロセスを、 初回プロンプト → オリジナル画像 → 修正プロンプト → 修正後画像 の流れで紹介します。 例1: 3層アーキテクチャ図 ステップ1: 初回プロンプト SVG図解を生成してください。 タイトル: 3層アーキテクチャ 内容: Presentation Layer、Business Logic Layer、Data Access Layerの3層構造を示す図 各層に以下の情報を含めてください: - Presentation Layer: desktop_windows アイコン、説明「UI・ユーザーインターフェース (React, Vue.js, Angular)」 - Business Logic Layer: settings アイコン、説明「ビジネスロジック (Services, Use Cases, Domain Logic)」 - Data Access Layer: storage アイコン、説明「データアクセス (Repository, ORM, Database Queries)」 各層を矢印で接続してください。 ステップ2: オリジナル生成結果 問題点 : 説明文の font-size が大きすぎる(18px) 矢印が <path> + marker-end のカスタム実装 padding が不十分(40px)で要素が詰まって見える このとき僕は「あー、やっぱり文字はみ出てるし、矢印も微妙だな」って思いました。でも構造自体は正しいので、修正するだけで済むのが楽なんですよね。 ステップ3: 修正プロンプト Claude に以下を指示: 以下の修正を適用してください: 1. 説明文の font-size を 18px → 16px に縮小 2. 矢印を Material Icons `arrow_downward` に置換 3. padding を 40px → 50px に拡大して余白を確保 ステップ4: 修正後の結果 改善点 : 説明文が矩形内に余裕を持って収まる Material Icons で統一されたデザイン 適切な余白で視認性が向上 これで見た目がかなりすっきりしました。僕的にはこのレベルなら公開用として十分使えると思います。 例2: ユーザー認証フロー ステップ1: 初回プロンプト SVG図解を生成してください。 タイトル: ユーザー認証フロー 内容: ログインから認証情報検証、セッション確立までのプロセスフロー 以下のステップを含めてください: 1. 開始(楕円形、緑色) 2. 認証情報入力(矩形、青色) 3. 認証情報検証(矩形、青色) 4. セッション確立(矩形、青色) 5. 完了(楕円形、赤色) 各ステップを矢印で接続してください。 ステップ2: オリジナル生成結果 問題点 : 全4箇所の矢印がカスタム実装( marker-end 使用) 矢印とステップの重なりが見える ステップ間の padding がバラバラ フロー図って矢印が命なんですが、カスタム矢印だと統一感がなくなるんですよね。 ステップ3: 修正プロンプト 以下の修正を適用してください: 1. 全4箇所の矢印を Material Icons `arrow_downward` に置換 2. ステップ間の padding を 50px に統一 3. 矢印とステップの位置を調整して重なりを解消 ステップ4: 修正後の結果 改善点 : Material Icons で統一された矢印 各ステップ間の余白が均一 すっきりとした視覚的な流れ これでフローが追いやすくなりました。技術ブログの図解としては十分なクオリティだと思います。 例3: Before/After 比較図 ステップ1: 初回プロンプト SVG図解を生成してください。 タイトル: 図解作成の時短効果比較 内容: 手動作成とSkill生成の作業時間・効率を比較するBefore/After図 Before側(左側、赤色): - 作業時間: 45分 - ツール: Figma / PowerPoint - 課題: 時間がかかる After側(右側、緑色): - 作業時間: 15分 - ツール: Claude Code Skill - 内訳: 生成5分 + 修正10分 - 効果バッジ: 67% 時短! BeforeからAfterへ横向き矢印を配置してください。 ステップ2: オリジナル生成結果 問題点 : 横向き矢印がカスタム実装( <path> + marker-end ) Before/After の横にアイコン(警告・チェックマーク)があり、「作業時間」と重なる 「作業時間」と数値(45分・15分)の間隔が狭い 矢印の位置が中央からずれている このときは「うーん、情報詰め込みすぎて見づらいな」って感じでした。 ステップ3: 修正プロンプト Claude に以下を指示: 以下の修正を適用してください: 1. 横向き矢印を Material Icons `arrow_forward` に置換 2. Before/After の横のアイコンを削除してテキストを中央配置 3. 「作業時間」と数値の間隔を 30px → 40px に拡大 4. 矢印を Before/After セクション全体の中央(y=368付近)に配置 ステップ4: 修正後の結果 改善点 : Material Icons で統一された横向き矢印 Before/After テキストがすっきりと中央配置 「作業時間」と数値の間に適切な余白 矢印が視覚的に中央に配置され、バランスが向上 これで見やすくなりました。Before/After図は情報量が多いので、余白をしっかり取るのが大事ですね。 Mermaid.js との使い分け 僕が以前書いた記事「 ClaudeでMermaid図作成を自動化!2時間→5分の劇的時短術【Live Editor活用】 」で紹介している Mermaid.js は、 システムチックな内容 を表現する際に結構高い精度で図を作ってくれる最高なツールです。 一方で、 概念的な話 になると Mermaid だと無機質になってしまうケースがあるんですよね。そこで SVG 直接生成の出番です。 具体的な使い分け 用途 推奨アプローチ 理由 例 システム図 Mermaid.js 記法が簡単、高精度 クラス図、シーケンス図、ER図 概念図 SVG 直接生成 ビジュアルで魅せられる アーキテクチャ概念図、比較図 データフロー Mermaid.js 専用記法で効率的 パイプライン、処理フロー デザイン重視 SVG 直接生成 色・レイアウトの完全制御 ブランディング重視の図解 Material Icons SVG 直接生成 Mermaid は非対応 Google Cloud アイコン使用 僕の実践的な使い分け基準 開発フェーズ別 : 記事の下書き段階 : Mermaid.js(速さ重視、素早くイメージ共有) 公開用の図解 : SVG 直接生成(品質重視、ビジュアルで差別化) 内容の性質別 : 技術的な関係性 : Mermaid.js(クラス継承、API 呼び出し順序など) コンセプト・アイデア : SVG 直接生成(3層アーキテクチャの概念、Before/After など) 結論 : Mermaid と SVG は競合ではなく 補完関係 。両方使いこなすことで、技術ブログの図解表現力が大幅に向上します。 僕の場合、システム図はMermaidでさくっと作って、ビジュアルで魅せたい図はSVGで作る、みたいな使い分けをしていますね。 まとめ Claude Code Skill を使った SVG 図解自動生成により、 図解作成時間を67%削減 できました!ただし、完璧な図解が一発で生成されるわけではなく、以下のような修正が必要になることが多いですね: よくある修正内容 font-size の調整(18px → 16px) padding の拡大(40px → 50px) カスタム矢印を Material Icons に置換 配置の微調整 それでも、Figma で一から作るより圧倒的に速いです。僕の場合、図解作成が億劫で記事執筆が進まない…ということがなくなりました。 この記事で得られる3つのメリット 時短効果 : 45分 → 15分(67%削減) 再現性 : Skill をコピーすればチーム全員が同じ品質で図解作成可能 継続的改善 : 修正プロンプトを蓄積してベストプラクティスを共有できる 次回以降の技術解説シリーズ 今回は SVG 図解の自動生成に焦点を当てましたが、今後は以下の内容を解説していきます! HTML 図解自動生成 (Tailwind CSS 使用) SVG → PNG 変換自動化 (CairoSVG) HTML → PNG 変換自動化 (Playwright) ブログやコンテンツを定期的に発信している方は、ぜひ参考にしてみてください!質問や感想は、コメント欄でお待ちしております。 参考リンク Claude Code Claude Code 公式ドキュメント ClaudeでMermaid図作成を自動化!2時間→5分の劇的時短術【Live Editor活用】 Material Design & Icons Material Icons Material Symbols(推奨) Google Cloud Icons アクセシビリティ WCAG 2.1 Level AA デザインパターン C4 Model – Software Architecture Visual Hierarchy Guide UI Color Palette Best Practices ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 図解作成が驚くほど楽に!Claude SkillでSVG自動生成 first appeared on SIOS Tech. Lab .
アバター
今月リリースされたばかりのサービス「Studio.Stock」を紹介する記事です。 機が熟した Studio.Stockは、AIの技術に、参加する画像クリエイターのセンス、運営する編集者の審美眼が加わった、ある意味で「最強」の「フォトストックサービス」です。 掲載されている素材画像はすべて、クリエイターがAIで生成したもの。 https://stock.studio.design 利用者は、おしゃれな「フォト」を選ぶだけ。 ウェブやプレゼンテーションなど、商用利用も含めてクレジット表記不要、無料で画像を利用ができます。 AI生成画像の特性を活かして、素材画像として「都合の良い」モチーフ、構図、ライティングの作品が次々にストックされていくことが想像できます。 Googleが今年リリースした、Geminiの画像生成「Nano Banana」は革新的で、 とてもリアルな画像生成が、簡単にできるようになりました 。 「AIで作成した写真的画像は、どこか不自然、質感がヌルッとしている」といった違和感が払拭されました。 つまり、この分野は「不気味の谷を超えた」と言えそうです。 シンプル Studio.Stockは、以前 このブログで紹介した「Unsplash」 と同様に、すっきりシンプルなUI。 シンプルなだけではなく、色をキーにした画像検索や、切り抜きや縦横比変更、プロンプトで加工、など便利な機能も盛り込まれています。 日本 国際的なフォトストックサービスでは、日本人モデル、風景、食べ物など、日本の写真のバリエーションが少ない傾向にあります。 日本のフォトストックサービスは、テイストが合わず、写真で利用に至らないこともありました。 Studio.Stockは、画像のモチーフを日本のものを中心に、企画されているようです。(現時点では) 厳選 歴史の長い他のフォトストックサービスには、写真やイラスト、AIによるフォトリアルな画像も多く登録されています。 選択肢が多いのは良いのですが、その分、画像を探すのに時間を要します。 Studio.Stockの世界観は限定されていますが、このテイストが気に入れば、すぐに高品質な画像にたどり着けるでしょう。 使い分け AI製画像が不気味の谷を超えても、やはり撮影された写真が適しているケースは多くあります。 また、一定以上の規模の案件や、印刷物で利用する場合は、高解像度の画像が必要であったり、ライセンス拡張が必要な場合もあります。 有償、無償合わせて、状況に合ったサービスを利用するのも大切かと思います。 まとめ 今の技術とスタイルが、小気味良く具体化されたStudio.Stock。 今後、参加するAIクリエイターは増え、有料機能を含めた機能の更新もあるようです。 このサービスの親サービスとも言える『ノーコードWeb制作プラットフォーム「Studio」』のWeb制作でも、Studio.Stock画像がシームレスに利用できるようになることも想像されます。 Studio.Stockについては、公式の記事にわかりやすい説明がありますので、そちらもご覧ください。 https://studio.design/ja/whats-new/studiostock ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post AI画像は不気味の谷を超えたか? – Studio.Stock first appeared on SIOS Tech. Lab .
アバター
はじめに こんにちは、サイオステクノロジーの安藤 浩です。 AWS認定ソリューションアーキテクト アソシエイト試験(AWS SAA-C03)に合格したので、やったことを記載します。(合格してから投稿が遅くなっていました) 実務でAWSを利用する予定だったこととクラウドはAzureは今まで経験してきたためクラウドの体系的な知識をつけておくのは良いかなと思ったため、受験しようと思いました。 AWS 認定資格 ソリューションアーキテクト アソシエイトとは? AWS認定ソリューションアーキテクト – アソシエイト(SAA-C03)は、AWSクラウドにおけるソリューション設計の基礎的なスキルを証明する認定資格です。 試験の概要 試験時間 : 130分 問題数 : 65問(選択問題) 合格ライン : 720点/1000点 試験形式 : CBT(テストセンター or オンライン監督付き) 試験費用 : 150USD(20,000円) 有効期限 : 3年間 対象者 以下のような方に適した資格です。 AWSクラウドで1年以上の実務経験を持つ方 AWSサービスを使ったソリューション設計の知識を身につけたい方 クラウドアーキテクチャの基礎を体系的に学びたい方 AWS上でのコスト効率的なシステム設計を理解したい方 私の簡単な経歴 10年程度のエンジニア AWS実務経験ほぼなし 1〜2年前に個人的にVPCやサブネットなど知識が薄そうな部分をハンズオン形式で以前やったことがある程度 Azure 中心での実務経験あり 学習内容 学習期間・時間 期間 : 7月中旬〜10月頭 平日 : 1-2時間 (朝 or 子供が寝てから) 休日 : 4-5時間 途中、実務が忙しくなりできていない期間もありました。 使用教材 Udemy問題集 【SAA-C03版】これだけでOK! AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座 実際は初めのほうの動画を見てハンズオンもすると2、3倍くらいかかりそうなことがわかったので、以下の動画やハンズオンをしてみました。 IAM の概要把握 VPC、サブネット、S3などのハンズオン セキュリティ関係のリソースの概要 など すべての動画で50時間くらいあるので、すべての動画をみてハンズオンをする時間はなさそうなので、出来る限り概要を把握して早めに以下の模擬試験をやってみることにしました。 【2025年版】AWS認定ソリューションアーキテクト アソシエイト模擬試験問題集(6回分390問) 1週目で1つの模擬試験を終わるまでに5日くらいかかってしまいました。 説明を読むのも結構時間がかかるので、推奨されるアーキテクチャや利用用途などを聞いて Claude やGemini で理解しました。 また、夜に学習すると眠くなってくるので、出来るだけClaude やGeminiへ質問をして、間違えた問題を中心にNotionにネットワーク系、コンテナ系、認証系などで分類していきました。ClaudeやGeminiには 試験での判断フロー、図式、覚えるべきポイント、ほかの選択肢が不正解である理由、実際の設計パターンなどをまとめて質問して内容をみていました。 おそらく、3週目くらいで5割くらい得点が取れるようなったかと思いますが、72%が合格ラインなので全体で80%くらいとれるまでを目指していました。最終的に5週くらいして7-8割くらいになった状態でした。 このあたりから間違えた問題をまとめたNotionのページやClaude やGemini に質問をして説明をみたり、図解してもらうなどして理解を深めていきました。 Ping-tも無料枠で少しやりましたが、あまり多く手を出すと理解が浅くなるかなと思い途中でやめました。 試験直前の1週間 試験対象のAWSサービス を見て、このサービスは何ができるか、どんなサービスと組み合わせるのか、違いなどを空で言えるようにしました。 分析 系のサービス(例: Amazon Athena, AWS Glue, Amazon Kinesis Stream, Amazon Kinesis Data Firehose など)、 ネットワークとコンテンツ配信 はなかなか覚えられなかったので、Notionにカテゴライズしたものを見て復習しました。 試験当日・受験後 自宅でも受けられますが、部屋を片付けるのが面倒なのでテストセンターで受験しました。初めてテストセンターで受けたのでノイズを遮断するヘッドセットの使い方がわからなかったことや、画面上の問題を読むのに慣れるまでやや時間がかかりました。 試験時間とどのくらいの件数を解答中に解答できてないとまずいかをちゃんと把握できている必要があったかと思います。見直す時間がほぼなかったことが反省点でした。 また、Budget, Cost Explorer などの問題がありコスト系のサービスをほぼ学習していなかったのでこの点も反省点です。 受験結果 720/1000 が合格ラインで731/1000 で合格ラインギリギリでした。 まとめ 以下、反省点を踏まえてまとめです。今後、試験を受ける際は以下の点に気を付けたいと思います。また、受験される方の参考になればと思います。 サービスを網羅的  に学習する AI活用 (Claude、Gemini)で効率化 問題演習メイン で弱点部分を見つける 時間配分の練習 は必須(私のように焦らないために) 試験だと思って問題を解く 参考URL AWS Certified Solutions Architect – Associate (SAA-C03) 試験ガイド AWS 認定ソリューションアーキテクト – アソシエイト認定 【SAA-C03版】これだけでOK! AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座 【2025年版】AWS認定ソリューションアーキテクト アソシエイト模擬試験問題集(6回分390問) ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post AWS 認定資格 ソリューションアーキテクト アソシエイトに合格しました first appeared on SIOS Tech. Lab .
アバター
5秒でわかる:この記事の内容 タイトルは挑発的ですが、真面目な技術記事です。 やったこと : ブログ記事のHTML→Markdown変換を実装 トークン削減率:平均 20.7% (3記事で実測) 既存実装と組み合わせて累積 65%削減 を達成 得られるもの : markdownifyライブラリを使った実装方法(コード付き) 段階的なトークン削減の実測データ WordPressブログのスクレイピングからMarkdown化まで 対象読者 : AIを活用したブログ執筆をしている人 RAG(もどき)システムを構築したい人 トークン削減に興味がある技術者 関連記事:より深く理解するために この記事は「AI活用ブログ執筆ワークフロー」シリーズの一部です。以下の記事を読むと、さらに理解が深まります。 必読 : 検証→記事化ワークフロー → 「RAGもどき」のアイデアを初めて紹介した記事。本記事はこのアイデアの実装編です。 あわせて読みたい : Claude Code Skills 実装ガイド → 今回の実装をClaude Code Skillとして統合する方法を解説。 3フェーズ開発 → AI活用開発ワークフローの基礎。検証→実装→記事化の流れ。 仕様書アレルギー克服 → AI活用で仕様書作成を効率化する方法。ワークフローの土台。 法的注意:必ずお読みください この記事の実装は SIOS Tech Lab専用 です。他サイトへの適用には、必ず事前の許可取得が必要です。無断スクレイピングは法的リスクがあります。詳細は本文の「 重要:本記事の対象範囲と法的注意事項」をご確認ください。 はじめに ども!記念すべき200本一本前のブログを執筆している龍ちゃんです。最近はブログの執筆が爆速になっているのですが、やはり検証リポジトリに執筆環境を統合したのが影響が大きかったと思います。執筆からレビューまで贅沢にClaude Codeを活用させてもらっています。 今回は、 執筆環境を作成する際に「RAGもどき」システム を作っているのですが、そちらの実践編です。「RAGもどき」というのは、ベクトルストアなんて贅沢なものは人間の頭で代用して、ファイルベースでファイルをローカルに管理するという人力の仕組みですw。 「RAGもどき」について ちなみに、この「RAGもどき」という表現ですが、実は RAGの定義からすると「もどき」じゃない んです。 RAGの本質とは? 原典論文 :Lewis et al. (2020) “ Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks ” (NeurIPS 2020) この論文では、RAGを「 パラメトリック(事前訓練済みseq2seqモデル)と非パラメトリック(検索可能な外部知識)メモリを組み合わせる 」汎用的なアプローチと定義しています。 重要なポイント : ベクトルストアは 必須要件ではない (知らなかった!) 論文中ではWikipediaの密集ベクトルインデックスを使用していますが、これは一例 検索可能な外部知識源であれば、どのような形式でも良い つまり、ファイルシステム上のMarkdownファイル群も、立派な「検索可能な外部知識源」なんです。 本記事のアプローチ : ローカルファイルベース : Claude Codeのコンテキストにブログ記事(.mdファイル)を含める 人間が選択 : AIの自動検索ではなく、自分(執筆者)が関連記事を手動で選択 小規模に最適 : 数十〜数百件のブログ記事セットに向いている 高精度 : 自分が書いた記事は自分が一番の専門家!的確な選択が可能 厳密に言えば : RAGシステムの「Retrieval(検索・取得)」部分を人間が担当している形です。医療や法律などの専門分野では、専門家が知識ベースを手動でキュレーション(厳選)してからRAGシステムに組み込むアプローチが取られており、本記事のアプローチはその簡易版と言えます。 本記事での呼び方 : 親しみやすさを重視して「RAGもどき」という表現を使っていますが、技術的には立派なRAGアプローチです。でも「もどき」って書いていると、RAGに詳しい人が気になって読んでくれるかな…とか、親しみやすさが出るかな…と思って….. ブログの取得に関してをスクリプト化して、Claude CodeのSkillとして登録することでURLを投げるだけでローカルに投稿済みのブログを取得する仕組みの実装についてトークン圧縮・可読性の観点から解説していきます。 重要:本記事の対象範囲と法的注意事項 本記事の実装について この記事は SIOS Tech Lab(https://tech-lab.sios.jp)のブログ記事 を対象としたHTML→Markdown変換の実装例です。 対象読者 : SIOS Tech Labの記事を扱う方(社内利用) WordPressベースのブログをスクレイピングしたい方 同様のHTML構造を持つサイトを扱う方 この実装の前提 : WordPressベースのブログサイト メインコンテンツが section.entry-content に格納されている OGPメタタグが適切に設定されている 注意 : CSSセレクタやHTML構造は他サイトでは異なる可能性があります。適宜カスタマイズが必要です。 他サイトへの適用時の法的注意 この記事の実装を 他サイト に適用する際は、以下の点に十分注意してください。 法的リスク : 無断スクレイピングは 利用規約違反 や 不正アクセス禁止法違反 に該当する可能性があります 最悪の場合、 民事訴訟 や 刑事告訴 のリスクがあります 「技術的に可能」≠「法的に許可されている」 必ず実施すべきこと : 利用規約の確認 robots.txtの確認(スクレイピング禁止の記載がないか) サイトの利用規約を熟読 自動アクセスが明示的に禁止されていないか確認 許可の取得 サイト運営者に事前に連絡 スクレイピングの目的を説明 書面またはメールでの許可を取得(証拠として保存) 負荷への配慮 アクセス頻度を制限(リクエスト間隔を設ける) サーバーに負荷をかけない 深夜帯など、アクセスが少ない時間帯に実行 安全なスクレイピング対象 : 自社サイト(許可不要) 明示的に許可されているサイト(API提供など) パブリックドメインのデータ 危険なスクレイピング対象 : 利用規約で禁止されているサイト robots.txtで禁止されているページ 会員制サイト(ログインが必要な情報) 営業秘密や個人情報を含むデータ 免責事項 : 本記事の実装を使用したことによる法的トラブルについて、著者およびSIOS Technologyは一切の責任を負いません。ご自身の責任において、適切な許可を得た上で使用してください。 概要 以前の記事 でRAGもどきシステムのアイデアを紹介しました。既存のブログ記事をAIに読み込ませることで、記事の重複チェックや文体・構成の一貫性を保つという仕組みです。 実はその後、HTML形式でブログ記事を保存する実装は密かに動いていました。ヘッダーやフッター、サイドバーを除去して、メインコンテンツだけを抽出するシンプルな処理です。ページ全体から見ると50-60%のトークン削減を実現していて、それなりに機能していました。 しかし、使い続けるうちに新たな問題が見えてきました。 新たな課題 HTMLで保存してもトークンがまだ多い 特に長い記事(10,000トークン以上)では、HTMLタグ( <div> , <p> , <section> )がトークンを消費し続けていました。例えば9,470トークンの記事では、まだ削減の余地がありそうでした。 可読性の問題 HTMLタグが邪魔で、可読性が低い状態でした。人間が読むのが辛い状態です。 解決策:Markdown変換 そこで、 HTML → Markdown変換 を実装することにしました。 処理フローは以下の通りです: 生HTML(ページ全体) ↓ ContentCompressor(既存実装) 抽出HTML(記事本文のみ) ↓ HtmlToMarkdownConverter(今回実装)← NEW Markdown(最終形態) 削減効果 : 抽出HTML → Markdown: 20.7%削減 (今回実装) 生HTML → Markdown: 累積64.9%削減 (全体) 構造保持+可読性向上 この記事で学べること 処理フロー全体像 :生HTML → 抽出HTML → Markdown 実測データ :3記事で見る削減効果(段階別) 実装方法 :markdownifyライブラリとカスタマイズ 累積効果 :既存実装との組み合わせで65%削減 リポジトリ サンプルコード(公開リポジトリ) : uv-single-devcontainer/examples/blog-scraper すぐに試せる完全なサンプルコード uvを使った開発環境テンプレート README付きで使い方も簡単 HTMLの限界:なぜMarkdownが必要だったのか 既存実装の振り返り まず、既存のHTML抽出処理について軽く説明します。 RAGもどきのアイデア として、既存ブログ記事をAIに読み込ませる仕組みを考えていました。記事の重複チェック、文体・構成の一貫性確保が目的です。記事50103では アイデアのみ紹介 していましたが、実装詳細は未公開でした。 実は既に実装していた んです。HTML形式でブログ記事を保存するシステムです: ヘッダー・フッター・サイドバーを除去 メインコンテンツ( section.entry-content )のみ抽出 CSS装飾や不要な属性を削除 トークン削減率 : 50-60%(ページ全体から) シンプルな実装内容 : # CSSセレクタでメインコンテンツを抽出 target = soup.select_one("section.entry-content") # 不要なタグを削除 for tag_name in ["script", "style", "noscript"]: for tag in target.find_all(tag_name): tag.decompose() # 属性を削除(href/alt/srcは保持) self._remove_attributes(target) これだけのシンプルな処理ですが、それなりに機能していました。 新たに発見した課題 しかし、長い記事での問題が見えてきました(10,000トークン以上): 1. トークン数がまだ多い HTMLタグ( <div> , <p> , <section> )がトークンを消費していました。例えば9,470トークンの記事では、まだ削減の余地がありました。 2. 可読性の問題 HTMLタグで可読性が下がっていました。AIが構造を理解しづらく、人間が読むのも辛い状態です。 具体例で見るHTMLの冗長性 同じ内容をHTMLとMarkdownで比較してみましょう。 HTML(30トークン) : <section> <h2>見出し</h2> <p>これは段落です。</p> <ul> <li>項目1</li> <li>項目2</li> </ul> </section> Markdown(20トークン) : ## 見出し これは段落です。 * 項目1 * 項目2 削減率 : 33% HTMLタグの除去だけで、これだけトークンを削減できます。 解決策:Markdown変換への移行 なぜ最初はHTMLタグを残していたのか? 実は、HTMLタグを残していたのには理由がありました。 構造情報の保持が目的 でした。 <h2> , <ul> , <section> などのタグは、単なる装飾ではなく、文章の構造を表す重要な情報です。これを完全に削除してしまうと、AIが記事の階層構造を理解しづらくなる可能性がありました。 「見出しはどれか」「リストはどこか」「どの段落がどのセクションに属するか」といった情報は、AIが記事を理解する上で重要なんですよね。 でも、問題がありました: HTMLタグがトークンを消費し続ける 可読性が低い 人間が読むには辛い そこで考えたのが、 Markdownへの変換 です。 なぜMarkdownなのか? Markdownなら、当初の「構造を保持したい」という意図を守りつつ、トークン削減と可読性向上の両立ができます。 理由は4つあります: 構造を保持 見出し(H1-H6)、リスト、テーブル、コードブロック、リンク、画像など、必要な構造要素をすべて保持できます。HTMLタグの構造情報をそのまま引き継げるんです。 可読性が高い プレーンテキストに近く、AIも人間も読みやすい形式です。GitHubでのレビューも容易です。 トークン数が少ない タグが不要で、 ## 、 * 、 - 等の記号のみで表現できます。属性も不要です。 YAML frontmatter対応 メタデータを構造化して保存できます(title, url, image)。 converted_at でバージョン管理も可能です。 つまり、こういうことです: 構造情報は保持( ## , ### , * , - で表現) トークン数は大幅削減(HTMLタグが不要) 可読性も向上(プレーンテキストに近い) 構造を残したい という当初の意図を守りつつ、トークン削減と可読性向上の両立を実現できたわけです。 Markdownの実例 実際の出力例を見てみましょう。 YAML frontmatter : --- title: "記事タイトル" url: https://tech-lab.sios.jp/archives/50103 image: https://... converted_at: 2025-11-11T06:13:55 --- # 記事本文... メタデータが構造化され、記事本文はMarkdown形式で保存されます。 実装の詳細 処理フロー全体像 まず、処理フロー全体を把握しましょう。 3段階のトークン削減 : 📄 生HTML(ページ全体) ↓ ① ContentCompressor(メインコンテンツ抽出) 📄 抽出HTML(記事本文のみ) ↓ ② HtmlToMarkdownConverter(Markdown変換) 📝 Markdown(最終形態) 各段階の役割 : ContentCompressor : 不要な要素を削除 ヘッダー、フッター、サイドバー除去 script/style/noscript削除 不要な属性削除(href/alt/srcは保持) セレクタ: section.entry-content HtmlToMarkdownConverter : Markdown変換 HTMLタグ → Markdown記法 長いalt属性の簡略化 YAML frontmatter追加 トークン削減効果 : 生HTML → 抽出HTML: 50-60%削減 (既存実装) 抽出HTML → Markdown: 20.7%削減 (今回実装) 累積削減率 : 約 65% (生HTML → Markdown) ContentCompressor(既存実装) SIOS Tech Lab特有の実装 です。以下のHTML構造に依存しています: # SIOS Tech LabのHTML構造に特化したセレクタ target = soup.select_one("section.entry-content") # ← Tech Lab固有 # script/style/noscript削除 for tag_name in ["script", "style", "noscript"]: for tag in target.find_all(tag_name): tag.decompose() # 不要な属性削除(href, alt, srcは保持) self._remove_attributes(target) これだけのシンプルな処理 : ヘッダー・フッター・サイドバー除去 CSS装飾の削除 55.7%のトークン削減(35,420 → 15,680トークン) 他サイトへの適用時の注意 : section.entry-content は SIOS Tech Lab特有 のセレクタです あなたのサイトに合わせて変更してください: # 例: 別のWordPressテーマの場合 target = soup.select_one("article .post-content") target = soup.select_one("div.entry-body") 問題点 : HTMLタグが残っている( <div> , <p> , <section> ) 可読性が低い さらなる削減の余地あり → ここで Markdown変換 の出番です。 ライブラリ選定:6つの候補から選んだ理由 HTML→Markdown変換のために、6つのライブラリを比較しました。 比較したライブラリ : html2text markdownify (採用) html-to-markdown trafilatura html2md Pandoc markdownify採用理由 : BeautifulSoup統合 : 既存のHTMLパース処理を活用できる カスタマイズ可能 : MarkdownConverterクラスを継承して独自の変換ロジックを実装できる 高品質な変換 : テーブル、リスト、見出しを適切に処理 アクティブなメンテナンス : 継続的に更新されている BlogMarkdownConverterのカスタマイズ markdownifyの MarkdownConverter を継承して、 SIOS Tech Labのブログ記事用 にカスタマイズしました。 実装のポイント : class BlogMarkdownConverter(MarkdownConverter): def convert_div(self, el, text, *args, **kwargs): """div タグはテキストのみ抽出""" return text def convert_img(self, el, text, *args, **kwargs): """長いalt属性(100文字以上)は簡略化 SIOS Tech Lab特有の問題: - WordPressのMermaidプラグインがalt属性に図のコード全体を格納 - 例: alt="graph TD; A-->B; C-->D; ..."(数百〜数千文字) - これをそのままMarkdownに変換するとトークンを大量消費 """ alt = el.get("alt", "") src = el.get("src", "") if len(alt) > 100: return f"![image]({src})" # 簡略化 return super().convert_img(el, text, *args, **kwargs) カスタマイズ内容 : div / span : テキストのみ抽出(タグを除去) img : 長いalt属性を ![image] に簡略化( Mermaid図対応 ← Tech Lab固有) 長いalt属性の簡略化は、WordPressのMermaidプラグインがalt属性に図のコード全体を格納する問題に対応したものです。100文字以上のalt属性は ![image] として簡略化することで、可読性を保っています。 他サイトへの適用 : あなたのサイトでMermaid図を使っていない場合、この処理は不要かもしれません。サイトの特性に合わせてカスタマイズしてください。 完全な処理フロー 実装の詳細ステップを見ていきましょう。 1. HTML取得 (BlogScraper) soup = scraper.fetch_html(url) original_html = str(soup) # 生HTML(ページ全体) 2. メタデータ抽出 (OGPタグから) metadata = extract_metadata_from_html(original_html) # title, url, image を抽出 3. コンテンツ抽出 (ContentCompressor) extracted_element = compressor.extract_content(soup) extracted_html = str(extracted_element) # 記事本文のみ 4. 空白圧縮 compressed_html = compressor.compress_whitespace(extracted_html) 5. Markdown変換 (HtmlToMarkdownConverter)← NEW markdown_content = converter.convert(compressed_html, metadata) # YAML frontmatter + Markdown本文 6. トークン数計算 markdown_tokens = estimator.estimate_tokens(markdown_content) # 削減率を計算 7. Markdown保存 (.mdファイル) markdown_path.write_text(markdown_content, encoding="utf-8") トークン削減の流れ : 35,420トークン(生HTML) ↓ ContentCompressor(-55.7%) 15,680トークン(抽出HTML) ↓ HtmlToMarkdownConverter(-20.7%) 12,440トークン(Markdown) ↓ 累積削減率: 64.9% 実測データで見る効果 測定方法 実際の効果を測定するため、3件のSIOS Tech Labブログ記事で検証しました。 対象記事 : tech-lab-sios-jp-archives-50103 tech-lab-sios-jp-archives-50109 tech-lab-sios-jp-archives-50142 測定対象 : 生HTML : ページ全体(ヘッダー、フッター、サイドバー含む) 抽出HTML : ContentCompressorで抽出した記事本文のみ Markdown : HtmlToMarkdownConverterで変換後 測定指標 : トークン数(tiktoken相当のTokenEstimator) ファイルサイズ(UTF-8バイト数) 削減率(各段階での削減効果) 3記事の詳細データ 記事1: tech-lab-sios-jp-archives-50103(完全な削減データ) この記事では、生HTMLからの完全な削減プロセスを測定しました。 段階的な削減 : 段階 トークン数 削減量 削減率 生HTML(ページ全体) 35,420 – – ↓ ContentCompressor 15,680 19,740 55.7% ↓ HtmlToMarkdownConverter 12,440 3,240 20.7% 累積削減 – 22,980 64.9% HTML → Markdown のみの比較 : 指標 抽出HTML Markdown 削減量 削減率 トークン数 9,470 7,529 1,941 20.5% ファイルサイズ 36,690 bytes 28,934 bytes 7,756 bytes 21.1% Note : 抽出HTMLトークン数は、記事本文のHTMLファイルとして保存したもの(メタデータコメント含む) 記事2: tech-lab-sios-jp-archives-50109 指標 抽出HTML Markdown 削減量 削減率 トークン数 13,730 11,171 2,559 18.6% ファイルサイズ 54,152 bytes 43,938 bytes 10,214 bytes 18.9% 記事3: tech-lab-sios-jp-archives-50142 指標 抽出HTML Markdown 削減量 削減率 トークン数 6,850 5,268 1,582 23.1% ファイルサイズ 27,252 bytes 20,942 bytes 6,310 bytes 23.2% 平均削減率 3記事の集計結果です。 指標 平均値 測定ファイル数 3 平均 抽出HTML トークン数 10,017 平均 Markdown トークン数 7,989 平均トークン削減率 20.7% 平均ファイルサイズ削減率 21.1% トークン削減の要因分析 なぜこれだけのトークン削減が実現できたのか、要因を分析します。 主な要因 : 1. HTML構造タグの除去 (最大の要因) <div> , <span> , <section> → テキストのみ抽出します。CSSクラス、ID、その他の属性が完全に除去されます。 2. Markdownの簡潔な記法 <strong> → ** <em> → * <a href="..."> → (url) 3. 空白・改行の最適化 複数の連続する空白が単一のスペースに圧縮されます。 4. スクリプト・スタイルタグの除去 <script> , <style> , <noscript> が削除されます。 累積効果:生HTMLからの完全な削減 トークン削減の全体像 既存実装と今回の実装を組み合わせることで、生HTMLから約65%のトークン削減を実現しました。 3段階の削減プロセス : 📄 生HTML(ページ全体): 35,420トークン ↓ ContentCompressor ↓ 📄 抽出HTML(記事本文): 15,680トークン ← 55.7%削減 ↓ HtmlToMarkdownConverter ↓ 📝 Markdown(最終形態): 12,440トークン ← さらに20.7%削減 累積削減効果 : 削減量: 22,980トークン 累積削減率: 64.9% 各フェーズの詳細 フェーズ1: ContentCompressor(既存実装) 処理内容 : CSSセレクタでメインコンテンツ抽出 ヘッダー、フッター、サイドバー除去 script/style/noscript削除 不要な属性削除 実装 : シンプルな抽出処理(数行のコード) 削減率 : 55.7% 削減量 : 19,740トークン 例 : 35,420 → 15,680トークン 課題 : HTMLタグが残り、可読性が低い フェーズ2: HtmlToMarkdownConverter(今回実装)← 本題 処理内容 : HTMLタグ → Markdown記法 構造タグ(div/span)除去 属性削除 長いalt属性簡略化(Mermaid図対応) YAML frontmatter追加 実装 : markdownifyライブラリ+カスタマイズ 削減率 : 20.7% 削減量 : 3,240トークン 例 : 15,680 → 12,440トークン メリット : トークン削減+可読性向上 相乗効果 : シンプルな既存実装(フェーズ1) 高度なMarkdown変換(フェーズ2)← 今回の焦点 組み合わせで65%削減を実現 可読性の向上 トークン削減だけでなく、可読性も大幅に向上しました。 HTML形式 (可読性:60点): <section> <h2>見出し</h2> <p>これは段落です。<strong>強調テキスト</strong>があります。</p> <ul> <li>項目1</li> <li>項目2</li> </ul> </section> Markdown形式 (可読性:90点): ## 見出し これは段落です。**強調テキスト**があります。 * 項目1 * 項目2 評価ポイント : AIにとって : 構造が明確で理解しやすい 人間にとって : プレーンテキストに近く読みやすい GitHubレビュー : diffが見やすい 実践:今すぐ試せる 実行前の確認事項 この実装を実行する前に : SIOS Tech Labの記事をスクレイピングする場合 : 外部の方は事前に許可を取得してください 社内利用の場合も、用途を明確にしてください 他サイトをスクレイピングする場合 : 必ず利用規約とrobots.txtを確認 サイト運営者の許可を取得 無断実行は絶対にしないでください 負荷への配慮 : 大量の記事を一度に取得しない リクエスト間隔を設ける(例: 1秒以上) サーバーに負荷をかけないよう注意 重要 : スクレイピングは「できる」ことと「やって良い」ことは別です。必ず法的・倫理的な確認を行ってください。 実際にブログスクレイパーを試してみましょう。 サンプルコードの入手 重要 : このサンプルコードは SIOS Tech Lab専用 です。他サイトへの適用には、必ず事前の許可取得とカスタマイズが必要です。 完全なサンプルコードをGitHubで公開しています。 GitHubリポジトリ : https://github.com/Ryunosuke-Tanaka-sti/uv-single-devcontianer クローン方法 : git clone https://github.com/Ryunosuke-Tanaka-sti/uv-single-devcontianer.git cd uv-single-devcontianer/examples/blog-scraper スクレイパーの実行 セットアップ : # 依存関係をインストール uv sync 実行例 : # 単一URLをスクレイプ uv run blog-scraper https://tech-lab.sios.jp/archives/48173 # 複数URLを一度にスクレイプ uv run blog-scraper \ https://tech-lab.sios.jp/archives/48173 \ https://tech-lab.sios.jp/archives/50103 出力ファイル : output/tech-lab-sios-jp-archives-48173.md output/tech-lab-sios-jp-archives-50103.md 確認方法 : cat output/tech-lab-sios-jp-archives-48173.md | head -20 カスタマイズ(他サイト適用時) 他サイトに適用する場合のカスタマイズ方法 : 1. CSSセレクタの変更 : src/blog_scraper/content_compressor.py を開き、以下を変更: # SIOS Tech Lab用(デフォルト) target = soup.select_one("section.entry-content") # あなたのサイト用に変更 target = soup.select_one("あなたのサイトのセレクタ") セレクタの見つけ方 : ブログ記事ページをブラウザで開く 開発者ツール(F12)を開く 記事本文をインスペクト メインコンテンツを囲む要素のセレクタをコピー 2. robots.txtの確認 : # 対象サイトのrobots.txtを確認 curl https://example.com/robots.txt 3. メタデータ抽出の調整 (必要に応じて): src/blog_scraper/metadata_extractor.py でOGPタグ以外のメタデータソースを追加可能。 実行オプション さまざまなオプションが利用可能です。 出力先を変更 : uv run blog-scraper --output ./my-articles https://tech-lab.sios.jp/archives/48173 既存ファイルを上書き : uv run blog-scraper --force https://tech-lab.sios.jp/archives/48173 URLリストファイルから一括取得 : # urls.txt に1行ずつURLを記載 uv run blog-scraper --url-file urls.txt まとめ 本記事のポイント HTML→Markdown変換で実現したこと : トークン削減率:平均20.7% ファイルサイズ削減率:平均21.1% 可読性:60点 → 90点(主観) 既存実装との累積効果 : フェーズ1(コンテンツ抽出): 55.7%削減 フェーズ2(Markdown変換): 20.7%削減 累積削減率 : 約65% 実装のポイント : markdownifyライブラリ採用 BlogMarkdownConverterカスタマイズ YAML frontmatter対応 重要な注意事項 : この実装はSIOS Tech Lab特化です 他サイトへの適用には 必ず許可が必要 です 無断スクレイピングは法的リスクがあります 技術的に可能でも、倫理的・法的に問題がないか必ず確認してください Before/After 比較 指標 Before(抽出HTML) After(Markdown) 改善 トークン数 10,017 7,989 20.7%削減 可読性 60点 90点 50%向上 ファイル形式 .html .md 構造化 メタデータ コメント YAML frontmatter 明確化 次のステップ 今回の実装で、ブログ記事のトークン数を大幅に削減し、可読性も向上させることができました。 SIOS Tech Lab以外のサイトへの適用 : CSSセレクタの特定(開発者ツールで確認) 利用規約とrobots.txtの確認 サイト運営者への許可申請 content_compressor.py のカスタマイズ テスト実行とトークン削減率の測定 さらなる改善の可能性 : ベクトル検索の統合(真のRAG化) セマンティック検索(類似記事の自動検出) 記事化の完全自動化(検証 → research-doc.md → article.md) 関連記事 : 3フェーズ開発 仕様書アレルギー克服 検証→記事化ワークフロー ← RAGもどきのアイデア Claude Code Skills 実装ガイド ← Skillとしての統合方法 本記事 : RAGもどき進化編(実装詳細) 参考リンク 学術論文 Lewis, P., Perez, E., Piktus, A., Petroni, F., Karpukhin, V., Goyal, N., … & Kiela, D. (2020). “ Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks “. In Advances in Neural Information Processing Systems (NeurIPS 2020). RAGの原典論文 ベクトルストアが必須でないことを示唆 公式ドキュメント Claude Code 公式ドキュメント markdownify GitHub BeautifulSoup4 ドキュメント Markdown 記法 リポジトリ サンプルコード(公開リポジトリ) : uv-single-devcontainer/examples/blog-scraper すぐに試せる完全なサンプルコード uvを使った開発環境テンプレート README付きで使い方も簡単 おわりに ここまで読んでいただき、ありがとうございました! HTML→Markdown変換により、RAGもどきシステムがさらに進化しました。トークン20%削減+可読性向上により、既存記事をAIに読み込ませる際の効率が大幅に改善されました。 既存のシンプルなHTML抽出処理と組み合わせることで、累積65%のトークン削減を実現しています。これにより、より多くの記事をコンテキストに含められるようになりました。 最後に重要なお願い この記事の実装を試す際は、以下を必ず守ってください: 自社サイトまたは許可を得たサイトのみに適用 無断スクレイピングは絶対にしない サーバーに負荷をかけない配慮 法的・倫理的な問題がないか常に確認 技術は便利ですが、使い方を誤ると大きなトラブルになります。責任を持って使用してください。 ぜひ、あなたのプロジェクト( 適切な許可を得た上で )でも試してみてください。 質問や感想は、コメント欄でお待ちしております。また、Twitterのほうもよろしくお願いします! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post HTMLでブログ記事を保存してる奴、全員Markdownにしろ。AIが読みにくいでしょうが! first appeared on SIOS Tech. Lab .
アバター
はじめに ども!先週はいろいろなブログを記述していたら10本も投稿していた龍ちゃんです。執筆速度が爆速になっているのですが、Claude Code と協業するようになったのが要因ですね。それらに関しては「 【2025 年版】検証 → 記事化で知見を資産化!Claude Code×RAG もどきで AI 技術ブログ執筆を効率化 」でまとめています。今回は、そちらのブログで触れていた情報を収集するツールの呼び出しを Claude Code の Skill 登録してスムーズに呼び出せるようになったのでその話を共有していこうと思います。 皆さん、プロジェクト固有の便利なツールやスクリプト、 Claude Code に使ってもらえてますか? 僕も以前はこんな悩みを抱えていました: CLAUDE.md にツールの使い方を詳細に書いても、Claude Code が使ってくれない 「〇〇ツールを使って」と明示的に指示しないと実行されない ツール説明が CLAUDE.md に埋もれて、Claude Code が見つけられない 特に困ったのが、 プロジェクトが成長するにつれて CLAUDE.md がどんどん長くなり、気づいたら Claude Code がツール説明を無視するようになっていた こと。最初は1,000文字程度だった CLAUDE.md が、開発ワークフローやアーキテクチャ情報を追加していくうちに8,000文字を超えてしまい、その中に埋もれたツール説明を Claude Code が見つけられなくなってしまったんですよね。 ブログ記事をスクレイピングするツールを作ったのに、毎回「blog-scraper を使って」と明示しないと実行されない。「記事を取得して」と言うだけでは、Claude Code が適切なツールを選択してくれない…。これ、なんとかならないかなぁと思っていたわけです。 そこで試したのが、 .claude/skills/ ディレクトリに Skill ファイルを登録する方法 です。この仕組みにより、以下の成果を得られました: トリガーワードで自動認識 (「記事を取得して」→ 自動的に blog-scraper を実行) CLAUDE.md の肥大化を防止 (ツール説明を専用ファイルに分離) 一貫した出力報告 (Response フォーマットを定義) この記事では、 Pythonスクリプトを Claude Code の Skill として登録し、スムーズに呼び出す方法 を、実際のプロジェクト例とともに解説していきます。 記事の位置づけ この記事は、「 【2025 年版】検証 → 記事化で知見を資産化!Claude Code×RAG もどきで AI 技術ブログ執筆を効率化 」で紹介した RAG もどき(ブログ HTML 抽出ツール) を、より効率的に Claude に使ってもらうための実践編です。 なお、 Claude Skills は 2025年10月16日に Anthropic から正式に発表された新機能 です。本記事では、この新機能を実際のプロジェクトで活用した経験をもとに、実践的な登録方法と活用テクニックを解説します。 公式ドキュメント : https://code.claude.com/docs/en/skills この記事で学べること この記事を読むことで、以下の知識とスキルが得られます: 主要なポイント CLAUDE.md vs Skill の比較 ツール説明を CLAUDE.md に書く方法と Skill 化の違い Skill ファイルの構造 Claude が理解しやすい Skill ファイルの書き方 実装例: blog-scraper Python スクリプトを Skill として登録する具体例 MCP との比較 MCP、Skill、スラッシュコマンドの使い分け 実践的なテクニック .claude/skills/ ディレクトリの活用方法 “When to Use” によるトリガー定義 出力の解釈方法と報告フォーマットの定義 Markdown のコードブロックネスト問題の回避 前提条件 必要な知識 Claude Code の基本的な使用経験 プロジェクト固有のツール・スクリプトを持っている CLAUDE.md の基本的な理解 あると理解が深まる知識 RAG もどきシステムの概念 以下の記事を参照: 【2025 年版】検証 → 記事化で知見を資産化!Claude Code×RAG もどきで AI 技術ブログ執筆を効率化 本記事で扱わないこと MCP Server の詳細な実装方法 Python スクリプトの基礎 uv パッケージマネージャーの詳細 本記事は、 プロジェクト固有のツールを Claude Code の Skill として登録する方法 に焦点を当てています。 Before / After: Skill 登録の効果 まずは、Skill 登録前後の違いを見てみましょう。 Before: CLAUDE.md にツール説明を記載 別リポジトリでの例 :TypeScript で作成した fetch-blog-html.ts ツール CLAUDE.md に詳細な使用方法を記載していました(約8,000文字): # CLAUDE.md - Docs ツールガイド ## ツール一覧 ### fetch-blog-html.ts **目的**: SIOS Tech Lab ブログから HTML を取得し、調査ドキュメントと比較検証するためのツール **機能**: - ブログ記事の HTML を取得 - OGP 情報(タイトル、URL、画像)を抽出 - 不要な要素・属性を削除して圧縮 - Claude 用のトークン数を推定・表示 ## セットアップ ```bash cd /home/node/dev/docs npm install ``` ## 使用方法 ### 方法1: npm script を使用(推奨) ```bash cd /home/node/dev/docs URL="https://tech-lab.sios.jp/archives/XXXXX" npm run fetch-blog ``` ### 方法2: 直接実行 ```bash cd /home/node/dev/docs/tools URL="https://tech-lab.sios.jp/archives/XXXXX" npx ts-node fetch-blog-html.ts ``` 問題点 : 呼び出しの不確実性 : Claude Code が毎回 CLAUDE.md を参照するとは限らない コンテキスト埋もれ : CLAUDE.md が長くなると、ツール説明が埋もれる 明示的な指示が必要 : 「fetch-blog-html.ts を使って」と明示しないと使われない After: Skill ファイルに登録 現リポジトリでの例 :Python で作成した blog-scraper ツール .claude/skills/blog-scraper.md (約2,000文字): # Blog Scraper Skill SIOS Tech Lab のブログ記事をスクレイピングして、トークン数を削減した形式で保存します。 ## When to Use 以下の場合にこのスキルを使用してください: - ユーザーが SIOS Tech Lab のブログ記事の URL を提供し、その内容を保存したい場合 - ユーザーが「ブログをスクレイピングして」「記事を取得して」などと依頼した場合 - 複数の記事を一括で取得したい場合 ## Commands ### 単一 URL の取得 ```bash uv run --package sios-tech-lab-analytics-ga4-scraper blog-scraper [URL] ``` 例: ```bash uv run --package sios-tech-lab-analytics-ga4-scraper blog-scraper https://tech-lab.sios.jp/archives/48173 ``` ## Response to User ### 成功時 ``` ✅ ブログ記事のスクレイピングが完了しました。 【記事情報】 - タイトル: [記事タイトル] - トークン削減: [元のトークン数] → [削減後のトークン数] ([削減率]%削減) - 保存先: docs/data/blog/tech-lab-sios-jp-archives-[記事ID].html - ファイルサイズ: [サイズ] bytes ``` 改善点 : 自動認識 : トリガーワード(「記事を取得して」)で自動的にスキルを使用 専用スペース : .claude/skills/ という専用ディレクトリで管理 構造化 : Claude が理解しやすいセクション構造 プロアクティブ : ユーザーがツール名を知らなくても適切に使用される 体感の違い シナリオ : ユーザーが「https://tech-lab.sios.jp/archives/48173 の記事を取得して」と依頼 Before(CLAUDE.md) : CLAUDE.md を読み込む(必ずとは限らない) ツール説明を見つける 使用方法を理解する コマンドを組み立てる 実行 → 問題 : ツール名を明示しないと使われない可能性 → 失敗時 : fetchでページ全体を取得する After(Skill) : .claude/skills/blog-scraper.md を参照(優先的に読み込まれる) “When to Use” で「記事を取得して」がトリガーと確認 “Commands” から適切なコマンドを選択 実行 “Output Interpretation” に従って出力を解釈 “Response to User” のフォーマットでユーザーに報告 → 改善 : トリガーワードで自動認識、一貫した報告 技術的な違い:Progressive Loading なぜ Skill がスムーズなのか? その答えは Progressive Loading(段階的読み込み) という仕組みにあります。 CLAUDE.md のコンテキスト管理 プロジェクト開始時 ↓ CLAUDE.md 全文(8,000文字 = 約2,000トークン)を読み込み ↓ 常にコンテキストウィンドウに存在 ↓ 他の情報が追加されると、相対的に優先度が下がる ↓ ツール説明が埋もれる可能性 問題点 : 8,000文字の CLAUDE.md を常時読み込むため、コンテキストを圧迫 ツール説明が長文の中に埋もれて、Claude Code が見逃す可能性 Skills のコンテキスト管理 Skills は 3段階の段階的読み込み を採用: レベル1: Metadata のみ(起動時) プロジェクト開始時 ↓ 全 Skills の name + description のみ読み込み(各30-50トークン) ↓ 10個の Skill でも約500トークンのみ レベル2: SKILL.md 本文(必要時) ユーザーリクエストと description がマッチ ↓ 該当 Skill の SKILL.md 全文を読み込み ↓ 詳細な指示を取得 レベル3: サポートファイル(さらに必要時) SKILL.md に "see REFERENCE.md for details" などの参照 ↓ 必要な追加ファイルを読み込み トークン消費の比較 方式 起動時のトークン消費 実行時 CLAUDE.md 約2,000トークン(全文) 常時存在 Skills 約500トークン(10 Skills のメタデータ) 必要な Skill のみ読み込み これが「体感が良くなる」技術的な理由 : コンテキストウィンドウの効率的な使用 : 必要な情報だけを段階的に読み込む 確実な発見 : description が必ず読み込まれるため、Claude Code がトリガーを見逃さない 柔軟な拡張 : Skills を増やしても、起動時のトークン消費は最小限 注記 :Skill がトリガーされると、SKILL.md 本文が読み込まれます。 ただし、使用しない Skill は読み込まれないため、コンテキストウィンドウを効率的に使用できます。 実装例: blog-scraper の Skill 登録 実際に登録している blog-scraper ツールを例に、Skill ファイルの構造を解説します。 ツールの概要 目的 : SIOS Tech Lab のブログ記事をスクレイピングし、Claude AI 向けにトークン数を削減して保存 言語 : Python 3.12+ パッケージ管理 : uv (workspace 機能使用) CLI フレームワーク : Click 主要機能 : トークン削減 : 平均 87.4% 削減 元ページ全体: 26,811 トークン 圧縮後: 3,390 トークン robots.txt 自動確認 : 礼儀正しいスクレイピング レート制限 : 最低 1 秒間隔でリクエスト 複数 URL 対応 : バッチ処理とプログレスバー表示 実行方法(uv workspace) ルートディレクトリから実行 uv run --package sios-tech-lab-analytics-ga4-scraper blog-scraper [URL] コマンド例 # 単一 URL uv run --package sios-tech-lab-analytics-ga4-scraper blog-scraper https://tech-lab.sios.jp/archives/48173 # 複数 URL uv run --package sios-tech-lab-analytics-ga4-scraper blog-scraper \ https://tech-lab.sios.jp/archives/48173 \ uv + Ruff + mypyで構築する超軽量Python開発環境 – イメージサイズ削減・型安全性確保を実現 # URL ファイル uv run --package sios-tech-lab-analytics-ga4-scraper blog-scraper --url-file urls.txt 出力例 🚀 Blog Scraper 起動 📁 出力先: docs/data/blog 📝 処理対象: 1 件のURL 🤖 robots.txt確認中... ✅ robots.txt: 許可 📄 処理中: https://tech-lab.sios.jp/archives/48173 🔄 HTML取得中... 📋 タイトル: PCの環境構築を迅速かつ簡単に!dotfilesで設定管理を始めよう | SIOS Tech. Lab 🔧 コンテンツ圧縮中... 📊 トークン削減: 26,811 → 3,390 (87.4%削減) ✅ 保存完了: 14078 bytes ================================================== 📊 処理結果サマリー 成功: 1 スキップ: 0 エラー: 0 合計: 1 ================================================== 🎉 すべての処理が完了しました Skill ファイルの構造と設計 Skill ファイルは、Claude Code が理解しやすいように構造化されています。 YAML Frontmatter(メタデータ) Skill ファイルの先頭には、YAML frontmatter でメタデータを記述します。 必須フィールド name(Skill 名) : 制約 : 小文字、数字、ハイフン( - )のみ 最大長 : 64文字 推奨形式 : Gerund form(動名詞形) 良い例: processing-pdfs , analyzing-spreadsheets , blog-scraping 許容範囲: blog-scraper description(説明) : 制約 : 最大 1024文字 記述スタイル : 第三人称 内容 : Skill が何をするか(What) いつ使うべきか(When) 重要 : Claude Code がこの情報をもとに Skill を発見する 良い例 : --- name: blog-scraper description: "SIOS Tech Lab のブログ記事をスクレイピングして、トークン数を削減した形式で保存します。Use when the user provides a blog URL and wants to save its content." --- 悪い例 : --- name: BlogScraper # 大文字を含む(NG) description: "Helps with blogs" # 何をするか、いつ使うかが不明確 --- 任意フィールド version : バージョン管理(例: 1.0.0 ) dependencies : 必要なパッケージ(例: python>=3.8 ) allowed-tools : 使用を制限するツール(例: [Bash, Read, Write] ) 必須セクション 1. When to Use(トリガー定義) Claude Code がこのスキルを使うべき状況を明示: ## When to Use 以下の場合にこのスキルを使用してください: - ユーザーが SIOS Tech Lab のブログ記事の URL を提供し、その内容を保存したい場合 - ユーザーが「ブログをスクレイピングして」「記事を取得して」などと依頼した場合 - 複数の記事を一括で取得したい場合 設計ポイント : 具体的なトリガーワードを列挙 ユーザーの依頼パターンを網羅 2. Commands(実行コマンド) 実際に動作するコマンドを記載: ## Commands ### 単一 URL の取得 ```bash uv run --package sios-tech-lab-analytics-ga4-scraper blog-scraper [URL] ``` 例: ```bash uv run --package sios-tech-lab-analytics-ga4-scraper blog-scraper https://tech-lab.sios.jp/archives/48173 ``` 設計ポイント : プロジェクト固有のパス指定( --package ) 実際に動作する具体例 複数のユースケースを網羅 3. Output Interpretation(出力解釈) コマンド実行結果の解釈方法を説明: ## Output Interpretation ### 成功時の出力例 [実際の出力を貼り付け] この出力から以下の情報をユーザーに報告してください: - タイトル(「📋 タイトル:」の後の文字列) - トークン削減率(「📊 トークン削減:」の後のパーセンテージ) - 保存ファイルサイズ - 保存先パス 設計ポイント : 実際の出力例を記載 どの情報を抽出するか明示 出力フォーマットの変化に対応 4. Response to User(報告フォーマット) Claude Code がユーザーに報告する際のフォーマット: ## Response to User ### 成功時 ``` ✅ ブログ記事のスクレイピングが完了しました。 【記事情報】 - タイトル: [記事タイトル] - トークン削減: [元のトークン数] → [削減後のトークン数] ([削減率]%削減) - 保存先: docs/data/blog/tech-lab-sios-jp-archives-[記事ID].html - ファイルサイズ: [サイズ] bytes ``` 設計ポイント : 一貫性のある報告形式 ユーザーが知りたい情報を網羅 視覚的に分かりやすいフォーマット オプションセクション 5. Options(オプション説明) ## Options - `--force`: 既存ファイルを上書き - `--output [PATH]`: 出力ディレクトリを指定 - `--timeout [SECONDS]`: タイムアウト時間 - `--quiet`: 詳細メッセージを非表示 6. Important Notes(注意事項) ## Important Notes 1. **URL バリデーション**: `https://tech-lab.sios.jp/archives/` で始まる URL のみ受け付けます 2. **レート制限**: 最低1秒間隔でリクエストが送信されるため、複数URLの処理には時間がかかります 3. **robots.txt**: 自動的に確認され、禁止されている場合は処理を中断します 実装のステップ Step 1: Skill ディレクトリの作成 mkdir -p .claude/skills Step 2: ファイル構造の選択 Skills のファイル構造には 2つのパターン があります。 パターンA: シンプル(単一ファイル) .claude/skills/ └── blog-scraper.md 特徴 : シンプルなツールに最適 ファイル1つで完結 サポートファイルが不要な場合に推奨 本記事の採用パターン : blog-scraper はシンプルなツールのため、このパターンを採用 パターンB: ディレクトリ構造(公式推奨) .claude/skills/ └── blog-scraper/ ├── SKILL.md(必須) ├── REFERENCE.md(任意) ├── examples/(任意) └── scripts/(任意) 特徴 : 複雑な Skill に最適 サポートファイルを整理できる Progressive Loading を最大限活用 推奨ケース : 詳細なリファレンスを含む Skill 複数のスクリプトやテンプレートを含む Skill 段階的に情報を提供したい場合 公式の記載 : “Both approaches work identically.”(両方のアプローチが同じように動作する) どちらを選ぶべきか : シンプルなツール(本記事の blog-scraper)→ パターンA 複雑なツール(PDF処理、Excel操作など)→ パターンB Step 3: Skill ファイルの作成 パターンAの場合: .claude/skills/blog-scraper.md を作成 パターンBの場合: .claude/skills/blog-scraper/SKILL.md を作成 Step 4: Skill の記述 実践的なアプローチ : Claude Code に作成を依頼する 実は、Skill ファイルの作成は Claude Code に依頼するのが一番効率的 です。僕も基本的に Claude Code に作成してもらっています。 実際の作成フロー ポイント : 最初から Skill ファイルを書こうとしない。まず動かして、成功してから Skill 化する。 ステップ1: やってほしいことを詳細に説明 SIOS Tech Lab のブログ記事(https://tech-lab.sios.jp/archives/XXXXX)を スクレイピングして、以下の処理を行う Python スクリプトを作成してください: 1. 記事のメインコンテンツだけを抽出(広告やナビゲーションは除外) 2. トークン数を削減(不要な HTML タグやスタイル情報を削除) 3. docs/data/blog/ ディレクトリに保存 4. robots.txt を確認して、許可されている場合のみスクレイピング 5. レート制限を設けて、礼儀正しくアクセス 【要件】 - uv workspace の scraper パッケージとして実装 - コマンドライン引数で URL を受け取る - 複数 URL の一括処理にも対応 - プログレスバーで進捗を表示 ステップ2: Claude Code が実装して実行 Claude Code がスクリプトを作成し、実際に実行してくれます。この時点で動作確認をして、問題があれば修正を依頼します。 ステップ3: 成功した内容を参考に Skill 化を依頼 実行が成功したら、その結果を使って Skill ファイルを作成してもらいます: この blog-scraper ツールがうまく動作しました! 以下の実行結果を参考に、.claude/skills/blog-scraper.md を作成してください。 【実行結果】 $ uv run --package sios-tech-lab-analytics-ga4-scraper blog-scraper https://tech-lab.sios.jp/archives/48173 🚀 Blog Scraper 起動 📁 出力先: docs/data/blog 📝 処理対象: 1 件のURL 🤖 robots.txt確認中... ✅ robots.txt: 許可 📄 処理中: https://tech-lab.sios.jp/archives/48173 🔄 HTML取得中... 📋 タイトル: PCの環境構築を迅速かつ簡単に!dotfilesで設定管理を始めよう | SIOS Tech. Lab 🔧 コンテンツ圧縮中... 📊 トークン削減: 26,811 → 3,390 (87.4%削減) ✅ 保存完了: 14078 bytes 【トリガーワード例】 - 「ブログをスクレイピングして」 - 「記事を取得して」 - 「この URL の記事を保存して」 【必要なセクション】 - When to Use: いつこのツールを使うべきか - Commands: 実行コマンドの例 - Output Interpretation: 出力の見方 - Response to User: ユーザーへの報告形式 - Important Notes: 注意事項(robots.txt、レート制限など) なぜこのフローが効果的か : 動作確認済み : Skill 化する前に、ツール自体が動作することを確認できる 具体的な例 : 実際の出力を見ながら Skill ファイルを書けるので、正確な記述ができる トリガーワードの自然な発見 : 実際に使ってみて「こう言えば呼び出せそう」というワードが見つかる 反復改善 : 一度 Skill 化してから、使ってみて「ここはもっと詳しく」という調整がしやすい 作成後の調整ポイント : トリガーワードが十分か確認(実際に使ってみて追加) エラーケースを追加(robots.txt で禁止されている場合など) よくある使い方を Example Workflow に追加 Skill ファイルに含めるべきセクション (参考): タイトルと説明 When to Use(トリガー定義) Commands(実行コマンド) Options(オプション説明) Output Interpretation(出力解釈) Response to User(報告フォーマット) Important Notes(注意事項) Example Workflow(使用例) Step 5: テスト 新しいチャットを開始 トリガーワードで依頼 動作確認 Step 6: 改善 実際の動作を見て Skill ファイルを調整 コマンド例の追加 エラーケースの追加 MCP との比較 MCP (Model Context Protocol) Server メリット : Claude Desktop に完全統合 自動的にツールを認識 引数の自動補完 型安全性が高い デメリット : 実装が複雑(Python の mcp ライブラリ、サーバー起動) 設定ファイル( claude_desktop_config.json )の編集が必要 デバッグが難しい プロジェクトごとの設定が煩雑 Skill メリット : 実装が簡単 (Markdown ファイル 1 つ) 設定ファイル不要 すぐに使える デバッグしやすい(ファイルを編集するだけ) プロジェクト固有のツールに最適 デメリット : Claude が手動で Bash ツールを実行する形式 MCP ほどの自動化はない スラッシュコマンド メリット : 実装が簡単 ユーザーが明示的に制御 デメリット : ユーザーが /command-name で明示的に呼び出す必要がある 自動認識されない 比較表 項目 MCP Server Skill スラッシュコマンド 実装難易度 高 低 低 自動認識 ○ △ × 設定ファイル 必要 不要 不要 適用範囲 グローバル プロジェクト プロジェクト デバッグ容易性 低 高 高 推奨ケース 外部データ接続 手続き的知識 ワークフロー 結論 : MCP と Skill は補完的な関係にあります。外部システムとの統合には MCP、プロジェクト内部の CLI ツールには Skill が適しています。 ベストプラクティス 公式推奨事項 SKILL.md は500行以下に保つ 理由 : コンテキストウィンドウはシステムプロンプト、会話履歴、他の Skills で共有されます。 対策 : 詳細な情報は REFERENCE.md などのサポートファイルに分離し、Progressive Loading を活用します。 Progressive Disclosure を活用 構造例 : .claude/skills/ └── complex-skill/ ├── SKILL.md(概要と主要な指示) ├── REFERENCE.md(詳細なリファレンス) ├── examples/(使用例) └── scripts/(実行可能なユーティリティ) SKILL.md から see REFERENCE.md for details のように参照することで、必要な時だけ詳細情報を読み込めます。 全モデルでテスト 推奨 : Haiku、Sonnet、Opus の全モデルで動作確認 理由 : モデルによって Skill の理解度が異なる場合があるため、主要なモデルで動作を確認しておくことで、より安定した Skill を提供できます。 ファイルパスは Forward slash を使用 Windows でも : reference/guide.md reference\guide.md 理由 : クロスプラットフォームでの互換性を確保 1. トリガーワードを明確にする 良い例 : ## When to Use - ユーザーが「記事を取得して」「スクレイピングして」と依頼した場合 - ユーザーが SIOS Tech Lab の URL を提供した場合 悪い例 : ## When to Use - 必要に応じて使用してください 2. 実際に動作するコマンドを記載 良い例 : uv run --package sios-tech-lab-analytics-ga4-scraper blog-scraper https://tech-lab.sios.jp/archives/48173 悪い例 : blog-scraper [URL] # パスや実行方法が不明確 3. 出力の解釈方法を具体的に 良い例 : この出力から以下の情報をユーザーに報告してください: - タイトル(「📋 タイトル:」の後の文字列) - トークン削減率(「📊 トークン削減:」の後のパーセンテージ) 悪い例 : 出力を確認してユーザーに伝えてください 4. エラーハンドリングを含める ### エラー時の出力例 ``` ❌ HTTP エラー 404: https://tech-lab.sios.jp/archives/12345 ``` 対処法:URL が正しいか確認してください。記事が削除されている可能性があります。 5. ユーザーへの報告形式を統一 フォーマットを定義することで、一貫性のある体験を提供: ## Response to User ### 成功時 ``` ✅ [ツール名]の実行が完了しました。 【結果】 - 項目1: [値] - 項目2: [値] ``` セキュリティ上の注意 Skills は強力な機能ですが、適切に使用しないとセキュリティリスクがあります。 1. 信頼できるソースからのみインストール 信頼できないソースからの Skill は実行前に必ず内容を確認してください Skill ファイルは Claude Code に実行権限を与えるため、悪意のあるコマンドが含まれている可能性があります GitHub など公開されている Skill を使用する場合は、作成者の信頼性を確認しましょう 基本的に自作するのが良いと思います! 2. プロンプトインジェクションのリスク Skills はユーザー入力に基づいて動作するため、以下のリスクがあります: リスク例 : ユーザーが提供した URL や入力が、意図しないコマンドを実行する可能性 Skill の出力を悪用して、Claude Code に誤った指示を与える可能性 対策 : Skill 内で外部入力を扱う場合は、適切なバリデーションを実装 コマンド実行前に、実行内容をユーザーに確認する仕組みを検討 機密情報を含むプロジェクトでは、特に注意が必要 3. 実行前の確認を推奨 Skill が実行するコマンドを理解してから使用してください 特に、ファイルシステムへの書き込みやネットワークアクセスを伴う Skill は慎重に 本記事の blog-scraper も、robots.txt の確認やレート制限など、礼儀正しい実装を心がけています 4. プロジェクト固有の制約 機密情報を扱うプロジェクトでは、Skill の使用を制限することを検討 チーム開発では、Skill のレビュープロセスを確立することを推奨 .gitignore で Skill ディレクトリを除外する場合は、チームメンバーへの共有方法を検討 よくある課題と解決法 課題 1: Skill が認識されない 原因 : ファイルパスが間違っている Markdown の構文エラー 解決方法 : # ファイルパスを確認 ls -la .claude/skills/blog-scraper.md # Markdown の構文チェック cat .claude/skills/blog-scraper.md 課題 2: コマンドが実行されない 原因 : コマンド例が間違っている 実行環境の違い(ディレクトリ、パスなど) 解決方法 : # 手動でテスト uv run --package sios-tech-lab-analytics-ga4-scraper blog-scraper https://tech-lab.sios.jp/archives/48173 課題 3: 出力の解釈が間違っている 原因 : 出力フォーマットの変更 解釈方法の説明が不明確 解決方法 : 実際の出力例を Skill に追加 どの部分を抽出すべきか明記 まとめ この記事では、 Python スクリプトを Claude Code の Skill として登録し、スムーズに呼び出す方法 を解説しました。 CLAUDE.md vs Skill の結論 観点 CLAUDE.md Skill トリガー明確性 △ 不明確 ○ “When to Use”で明示 参照優先度 △ 他の情報に埋もれる ○ 専用ディレクトリで優先 構造化 △ 自由形式 ○ セクション構造 出力解釈 △ 推測ベース ○ 明示的に指示 報告フォーマット △ 不統一 ○ 定義済み デバッグ △ 長文の編集 ○ 独立ファイル 実装難易度 ○ 簡単 ○ 簡単 体感の改善理由 : Progressive Loading : メタデータのみ読み込み(30-50トークン)→ 必要時に詳細読み込み トリガー認識 : description が必ず読み込まれるため、Claude Code が確実に発見 コンテキスト効率 : 10個の Skills でも約500トークンのみ(CLAUDE.md は2,000トークン) 構造化情報 : セクション分けで Claude Code が段階的に理解 一貫性 : 報告フォーマット定義で毎回同じ品質 推奨ユースケース Skill が適している : プロジェクト固有の CLI ツール Python スクリプト、シェルスクリプト リポジトリ内のツール 手続き的な知識の提供 CLAUDE.md が適している : プロジェクト全体の開発ガイドライン 開発ワークフローの説明 アーキテクチャ情報 Skill として切り出せない一般的な説明 MCP が適している : 外部データソースとの接続 複数のプロジェクトで使用するツール 公開するツール リアルタイムデータアクセス 次のステップ 既存の CLAUDE.md 内のツール説明を Skill に移行 新しいツールを作成したら Skill ファイルも作成 Skill ファイルを継続的に改善(実際の使用経験に基づく) 参考リンク 公式ドキュメント Claude Skills 公式発表 : Claude Code Skills ドキュメント : カスタム Skill 作成ガイド : Skill ベストプラクティス : 公式 Skills リポジトリ : エンジニアリングブログ : 関連記事 RAG もどきシステム : 【2025 年版】検証 → 記事化で知見を資産化!Claude Code×RAG もどきで AI 技術ブログ執筆を効率化 ここまで読んでいただき、ありがとうございました! Skill 登録を実践することで、プロジェクト固有のツールが Claude Code によってスムーズに使われるようになり、開発効率が劇的に向上します。ぜひ、この記事を参考に、あなたのプロジェクトでも実践してみてください。 質問や感想は、コメント欄でお待ちしております。また、Twitter のほうもよろしくお願いします! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Claude Code Skills 実装ガイド:ローカルツールをスムーズに統合する方法 first appeared on SIOS Tech. Lab .
アバター
はじめに ども!最近またですね、新しい検証を進めるために環境構築をつらつらとやっている龍ちゃんです。AI開発をスムーズに進めるための環境構築を検証しているんですが、今回は uvのワークスペース機能 を使ったモノレポ環境について共有します。 前回の記事「 uv + Ruff + mypyで構築する超軽量Python開発環境 」では、単一プロジェクトでの開発環境最適化を紹介しました。今回は、その延長として 複数プロジェクトを1つのリポジトリで管理するモノレポ環境 を構築していきます。 この記事でわかること Pythonでモノレポを管理するのは大変ですよね。requirements.txtの手動管理、複数venvの環境切り替え、AI開発ツールとの相性…。 この記事では、 uvワークスペース を使って、これらの課題を「まるっと解決」する方法を紹介します。Node.jsのpackage.jsonのような自動管理が、Pythonでも実現できます。 この記事の流れ 従来のアプローチの課題 uvワークスペースによる解決 実装ガイド(10分で構築) 実際のプロジェクト例(GA4分析プロジェクト) **注** : 本記事ではuvワークスペースを紹介しますが、Poetry、PDM、 Hatchなどでも同様のモノレポ環境を構築できます。プロジェクトの 状況(既存ツール、チームの慣れ、安定性要件など)に応じて 適切なツールを選択してください。uvは2024年登場の新しいツールで、 特に速度を重視する新規プロジェクトに適しています。 pip + requirements.txt の根本的な問題 Pythonの依存関係管理で、こんな経験はありませんか? # パッケージをインストールしても... pip install flask # → requirements.txt は更新されない! # → 手動で追加するか、pip freeze を使う必要がある これが、PythonとNode.jsの 最大の違い なんですよね。 Node.jsとの比較 項目 pip + requirements.txt npm + package.json パッケージ追加 pip install X → 手動でファイル編集が必要 npm install X → 自動でファイル更新 パッケージ削除 pip uninstall X → 手動でファイル編集が必要 npm uninstall X → 自動でファイル更新 直接依存 vs 間接依存 区別困難( pip freeze で混在) 明確に分離 pip freeze の問題 pip freeze を使うと、直接依存と間接依存が混在して出力されます。 # pip freeze の出力 flask==3.0.0 click==8.1.0 # ← これは直接依存?間接依存? Jinja2==3.1.0 # ← これは直接依存?間接依存? Werkzeug==3.0.0 # ← これは直接依存?間接依存? MarkupSafe==2.1.0 # ← Jinja2が依存(間接依存の間接依存!) 問題点 : どれが直接依存で、どれが間接依存か判別できない パッケージを削除する時に「これは本当に削除して大丈夫?」と悩む requirements.txt が肥大化する モノレポでの2つのパターンとその課題 Pythonでモノレポを作るとき、これまで主に2つのパターンを試してきました。 パターン1: 各プロジェクトに個別venv monorepo/ ├── project-a/ │ ├── .venv/ # project-a専用の仮想環境 │ ├── requirements.txt │ └── src/ ├── project-b/ │ ├── .venv/ # project-b専用の仮想環境 │ ├── requirements.txt │ └── src/ └── project-c/ ├── .venv/ # project-c専用の仮想環境 ├── requirements.txt └── src/ メリット : 各プロジェクトの依存関係が完全に分離 プロジェクト間でバージョン競合が発生しない デメリット : IDE設定が煩雑(環境切り替えが必要) 共通依存関係(pandas など)が各 .venv に重複インストール VSCodeのインタープリター設定を頻繁に変更する必要がある VSCodeワークスペース(.code-workspace)でも解決しない問題 VSCodeには複数のフォルダを1つのワークスペースとして管理する機能があります。 // monorepo.code-workspace { "folders": [ { "path": "project-a" }, { "path": "project-b" }, { "path": "project-c" } ], "settings": { "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python" } } これで各プロジェクトが独立した設定を持てるんですが、 AI開発の観点では問題 があります。 AI開発ツール(Claude Code など)の視点で不利な理由 : AIは1つのVSCodeウィンドウ全体をコンテキストとして理解する フォルダ間の関係性を把握しにくい 「project-aのコードを参考にproject-bを修正して」といった指示が通りにくい 私の場合、Claude Codeを使って開発することが多いので、この点は結構重要でした。 パターン2: ルートに大きなvenv monorepo/ ├── .venv/ # 全プロジェクトの依存関係を含む ├── requirements.txt # 全プロジェクトの依存関係を手動管理 ├── project-a/ │ └── src/ ├── project-b/ │ └── src/ └── project-c/ └── src/ メリット : IDE設定が簡単(1つのvenvを指定するだけ) 共通依存関係の重複インストールがない デメリット : requirements.txtの手動管理が確実に必要 どのパッケージがどこで使われているか不明瞭 バージョン競合が発生しやすい パッケージ削除時の影響範囲が不明 例(ルートrequirements.txtの肥大化) : # monorepo/requirements.txt # project-a の依存関係 flask==3.0.0 pandas==2.2.0 # project-b の依存関係 django==5.0.0 pandas==2.2.0 # ← project-aと重複 # project-c の依存関係 fastapi==0.115.0 pandas==2.1.0 # ← バージョン競合!どちらを選ぶ? # これらは直接依存?間接依存?誰が使っている? click==8.1.0 jinja2==3.1.0 sqlalchemy==2.0.0 ...(100行以上続く) 問題点 : どのパッケージがどのプロジェクトで使われているか追跡困難 パッケージを削除する時に「本当に削除して大丈夫か」判断できない バージョン競合を手動で解決する必要がある 私も最初はこのパターンで試していたんですが、requirements.txtの管理が煩雑で、結構な時間のロスをしました。 package.jsonライクな自動管理 uvを使うと、Node.jsのpackage.jsonのような 自動管理 が実現できます。 uvの動作 # npm の場合 npm install express # → package.json が自動更新される! # uv の場合 uv add flask # → pyproject.toml が自動更新される! これは想像以上に効果的でした。特に複数プロジェクトを管理する場合、手動でrequirements.txtを編集する手間がなくなるだけで、開発体験が大きく変わります。 重要な3つの特徴 自動更新される依存関係ファイル uv add すると pyproject.toml が自動で更新される pip のように手動で requirements.txt を編集する必要がない 直接依存と間接依存の分離 pyproject.toml : 直接依存のみ(読みやすい、package.json と同じ) uv.lock : 全依存関係をロック(再現性、package-lock.json と同じ) ロックファイルによる再現性 uv.lock で全環境で同じバージョンを保証 バージョン競合を自動解決 単一venv + ワークスペース管理 uvワークスペースを使うと、 パターン2の利点(単一venv) と パターン1の利点(明確な依存関係) を両立できます。 uvワークスペースの構成 sios-tech-lab-analytics-ga4/ ├── .venv/ ← 単一の仮想環境(全ワークスペース共有) ├── uv.lock ← 統合ロックファイル ├── pyproject.toml ← ルート設定 └── application/ ├── batch/ │ ├── pyproject.toml ← バッチの依存関係(自動管理) │ └── src/ ├── frontend/ │ ├── pyproject.toml ← フロントエンドの依存関係(自動管理) │ └── app.py └── scraper/ ├── pyproject.toml ← スクレイパーの依存関係(自動管理) └── main.py ポイント : IDE設定が簡単(1つのvenvを指定するだけ) 各ワークスペースの依存関係は pyproject.toml で明確に管理 バージョン競合は uv.lock で自動解決 手動での requirements.txt 編集が不要 モノレポ構成によるAI開発体験の向上 私が実際にClaude Codeを使って開発していて感じたのは、 モノレポ構成そのものがAI開発ツールとの相性が良い ということです。 なぜモノレポがAI開発に向いているのか? 1. AIが全プロジェクトのコンテキストを一度に把握できる 従来のアプローチ(複数リポジトリ or 個別venv) : AIはリポジトリごとにコンテキストが分断される 「project-aのコードを参考にproject-bを修正して」という指示が難しい 複数のVSCodeウィンドウを開く必要がある モノレポ構成 : 単一のVSCodeウィンドウで全体を見渡せる プロジェクト間の依存関係や共通コードをAIが理解しやすい 「batchのコードを参考にfrontendを修正して」という自然な指示が通る これは Poetry、PDM、uvなど、どのツールでも共通 するモノレポの利点です。 2. 環境管理のシンプルさ 複数venvの環境では、AIがパッケージをインストールする際に「どのvenvにインストールすべきか」の判断が必要でした。 モノレポで単一venv(または統一された依存管理)を使うと: VSCodeのインタープリター設定は1つだけ 「今どの環境にいるのか」を意識する必要がない AIが想定外の環境にパッケージをインストールするリスクが低い uvワークスペースの追加メリット その上で、uvワークスペースには以下の利点があります: 自動管理による認知負荷の軽減 # uv の場合 uv add --package my-monorepo-batch pandas # → pyproject.toml が自動更新される # Poetry の場合(同様に自動更新) cd application/batch poetry add pandas # pip の場合(手動編集が必要) pip install pandas # → requirements.txt を手動で編集... 依存関係の追加・削除時に、AIに「pyproject.tomlを更新して」と指示する必要がありません。 高速なインストール 開発中に頻繁にパッケージを試すとき、uvの高速さ(pip比10-100倍)は体感できます。 しかし : これらは「AI開発に必須」ではなく、「開発体験を向上させる要素」です。Poetry、PDMでも同等の開発体験を得られます。 AI開発における依存管理ツールの選択 要素 影響度 プロジェクト構造の明確さ 最重要 ドキュメントの充実 最重要 モノレポ構成 重要 一貫性のある命名規則 重要 依存管理ツールの種類 影響は限定的 AIツールは依存管理ツールの種類を気にしません 。重要なのは、論理的なプロジェクト構造と良いドキュメントです。 実際の選択基準 AI開発においても、依存管理ツールの選択は従来の基準で問題ありません: 新規プロジェクト + 速度重視 → uv 既存Poetryプロジェクト → そのまま継続で問題なし チームがPEP準拠を重視 → PDM PyPA公式ツール希望 → Hatch さらに深くAI協業開発を学びたい方へ : モノレポ環境を整えた後、 AI協業開発環境の構築術|モノレポでビルド時間を大幅短縮するCLAUDE.md活用法 も参考にしてみてください。CLAUDE.md階層構造を使って、AIにプロジェクト全体像を理解させる方法を解説しています。 実装ガイド(10分で構築) それでは、実際にuvワークスペースを構築してみましょう。 ステップ1: ルート pyproject.toml の作成 [project] name = "my-monorepo" version = "0.1.0" requires-python = ">=3.12" [dependency-groups] dev = [ "ruff>=0.7.0", "pytest>=8.0.0", "mypy>=1.18.2", ] [tool.uv.workspace] members = ["application/frontend", "application/batch", "application/scraper"] [tool.ruff] line-length = 88 target-version = "py312" [tool.ruff.lint] select = ["E", "W", "F", "I", "N", "UP", "B"] [tool.mypy] python_version = "3.12" warn_return_any = true check_untyped_defs = true ignore_missing_imports = true ポイント : tool.uv.workspace.members で各ワークスペースを定義 ルートには開発ツール(ruff, pytest, mypy)を配置 コード品質設定(Ruff、mypy)は全ワークスペースで共有 ステップ2: 各ワークスペースの pyproject.toml 例: application/batch/pyproject.toml [project] name = "my-monorepo-batch" version = "0.1.0" requires-python = ">=3.12" dependencies = [ "pandas>=2.2.0", "python-dotenv>=1.0.0", ] 例: application/frontend/pyproject.toml [project] name = "my-monorepo-frontend" version = "0.1.0" requires-python = ">=3.12" dependencies = [ "streamlit>=1.40.0", "pandas>=2.2.0", "plotly>=5.24.0", ] ポイント : 各ワークスペースは独立した pyproject.toml を持つ 共通依存関係(pandas など)は uv.lock で自動的に1つのバージョンに統一される ステップ3: 依存関係のインストール # 全ワークスペースの依存関係を同期 uv sync # 特定のワークスペースにパッケージを追加 uv add --package my-monorepo-batch pandas # ルートワークスペースに開発ツールを追加 uv add --dev ruff pytest mypy 重要 : uv sync 1回で全ワークスペースの依存関係がインストールされます。これは、npmの npm install と同じ感覚ですね。 ステップ4: コマンド実行 # 特定のワークスペースのコマンドを実行 uv run --package my-monorepo-batch python application/batch/script.py uv run --package my-monorepo-frontend streamlit run application/frontend/app.py # 開発ツールの実行(ルートワークスペース) uv run ruff format . uv run mypy . uv run pytest 実際のプロジェクト例: GA4分析 私が実際に構築したGA4(Google Analytics 4)分析プロジェクトでの実装例を紹介します。 ワークスペース構成 sios-tech-lab-analytics-ga4/ ├── .venv/ # 単一の仮想環境 ├── uv.lock # 統合ロックファイル(206KB、1306行) ├── pyproject.toml # ルート設定 └── application/ ├── batch/ │ ├── pyproject.toml # GA4データ取得・変換 │ └── script.py ├── frontend/ │ ├── pyproject.toml # Streamlitダッシュボード │ └── app.py └── scraper/ ├── pyproject.toml # ブログデータ収集 └── main.py 各ワークスペースの役割 1. batch: GA4からのデータ取得・変換 # application/batch/pyproject.toml [project] name = "sios-tech-lab-analytics-ga4-batch" dependencies = [ "google-analytics-data>=0.18.0", "pandas>=2.2.0", "python-dotenv>=1.0.0", ] 2. frontend: Streamlitダッシュボード # application/frontend/pyproject.toml [project] name = "sios-tech-lab-analytics-ga4-frontend" dependencies = [ "streamlit>=1.40.0", "pandas>=2.2.0", "plotly>=5.24.0", ] 3. scraper: ブログデータ収集 # application/scraper/pyproject.toml [project] name = "sios-tech-lab-analytics-ga4-scraper" dependencies = [ "requests>=2.32.0", "beautifulsoup4>=4.12.0", "lxml>=5.0.0", "click>=8.1.0", ] [project.scripts] blog-scraper = "sios_tech_lab_analytics_ga4_scraper.main:main" ポイント : エントリポイント( [project.scripts] )を定義することで、 uv run blog-scraper でコマンド実行可能 共通依存関係の扱い pandas>=2.2.0 は batch と frontend で共有されますが、 uv.lock で自動的に1つのバージョン(2.2.1)に統一されます。 これにより、バージョン競合を気にせず開発できます。手動で調整する必要がないので、すごく楽ですね。 DevContainerとの統合 { "name": "Python Dev (uv + Ruff + mypy)", "build": { "dockerfile": "Dockerfile" }, "customizations": { "vscode": { "extensions": ["charliermarsh.ruff", "ms-python.python"], "settings": { "": { "editor.defaultFormatter": "charliermarsh.ruff", "editor.formatOnSave": true } } } }, "postCreateCommand": "uv sync" } ポイント : postCreateCommand: "uv sync" でコンテナ作成時に全依存関係を自動インストール チーム全員が同じ環境を共有できる まとめ 今回は、uvワークスペースを使ったPythonモノレポ管理の方法を紹介しました。 この環境で得られる4つのメリット package.jsonライクな自動管理 – pip + requirements.txtからの脱却 単一venv + ワークスペース管理 – IDE設定が簡単 AI開発ツールとの相性が抜群 – 全プロジェクトを一度に把握 バージョン競合の自動解決 – 手動調整が不要 Pythonのモノレポ管理が、Node.jsのように快適になります。 次のステップ 今回の記事 : 開発環境での構築(uvワークスペースの基本) 次回の記事 : デプロイ・本番環境への展開 GitHub ActionsでのUV対応 uvからrequirements.txtへの変換 コンテナビルドと本番環境での実行 ぜひ、あなたのプロジェクトでも試してみてください! 質問や感想は、コメント欄でお待ちしております。 参考リンク 公式ドキュメント uv公式ドキュメント – Workspaces uv公式ドキュメント – Projects 関連記事 uv + Ruff + mypyで構築する超軽量Python開発環境 AI協業開発環境の構築術|モノレポでビルド時間を大幅短縮するCLAUDE.md活用法 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post uvで解決!Pythonモノレポの依存関係管理【2025年版】 first appeared on SIOS Tech. Lab .
アバター
はじめに ども!前回「 DevContainer と uv で構築する爆速 Python 開発環境 」という記事を書いた龍ちゃんです。 この記事を社内で報告したところ、上司から「リンターとフォーマッターは何を使っているの?」という質問をいただきました。確かに、せっかくパッケージマネージャーに uv を採用しているなら、同じ Astral 社が開発している Ruff で統一した方が良いですよね! ということで今回は、 uv + Ruff で統一した Python 開発環境 を構築してみました。さらに、ベースイメージも見直すことで、 イメージサイズを 83%削減(1.63GB → 273MB) することに成功しています。 Streamlit を使ったデータ分析アプリをサンプルとして作成していますが、もちろん Streamlit 以外のプロジェクトでも利用可能です。リポジトリは公開しているので、必要な方はクローンして使ってみてください! リポジトリ: https://github.com/Ryunosuke-Tanaka-sti/uv-single-devcontianer.git 4 つの最適化ポイント 前回の環境から、大きく 4 つのポイントを最適化しました。それぞれ詳しく見ていきましょう。 ① ベースイメージの変更による劇的な軽量化 前回は mcr.microsoft.com/devcontainers/python:3.11 という Microsoft 公式の DevContainer 用イメージを使用していました。このイメージの利点は、デフォルトで vscode ユーザーが作成されていることと、Python 開発に必要なツールがプリインストールされていることです。 しかし、今回は 軽量性 を重視して python:3.12-slim に変更しました。結果は驚くべきもので、 イメージサイズが 1.63GB から 273MB へと 83%も削減 されました! 項目 Microsoft 公式 今回の環境 ベースイメージ mcr.microsoft.com/devcontainers/python:3.11 python:3.12-slim イメージサイズ 1.63GB 273MB 削減率 – 83%削減 軽量化の理由は明確で、Microsoft 公式イメージには Python 開発用のツールが豊富にプリインストールされています(git、Black、Flake8、mypy、isort など)。これらは便利ですが、今回は uv と Ruff で統一するため不要です。 python:3.12-slim は最小限の Python 環境(119MB)のみを含んでおり、必要なツールだけを追加することで無駄のない環境を構築できました。 イメージサイズの内訳: python:3.12-slim(ベース): 119MB git + curl のインストール: 101MB uv のインストール: 53.6MB 合計: 273MB ②Ruff へのツール統合でシンプルに 前回は Black、Flake8、isort と複数のツールを使用していましたが、今回は Ruff 1 つに統合 しました。 役割 前回 今回 フォーマッター Black Ruff リンター Flake8 Ruff インポート整列 isort Ruff ツール数 3 つ 1 つ 実行速度 通常 10-100 倍高速 Ruff は、Rust で実装された超高速リンター・フォーマッターで、Black、Flake8、isort、pyupgrade などの機能を統合しています。設定も pyproject.toml 内で完結するため、非常にシンプルです。 注意: 型チェック(mypy)は Ruff に含まれていません。型チェックが必要な場合は、引き続き mypy や Pyright などの型チェッカーを併用してください。Ruff は型アノテーションの書き方に関するリントルールを提供しますが、静的型解析は行いません。 ③ ユーザー管理の工夫 python:3.12-slim には vscode ユーザーが存在しないため、 devcontainer.json の features 機能を使って自動作成します。これにより、ホストの UID/GID と一致させることができ、パーミッション問題を回避できます。 ④ 型チェック(mypy)の統合で型安全性を確保 Python の型安全性を高めるため、 mypy による型チェック を開発環境に統合しました。 項目 従来の環境 今回の環境 型チェック なし / 手動セットアップ mypy 統合済み VS Code 連携 手動設定が必要 自動で有効化 実行 個別にコマンド実行 保存時に自動チェック 設定の複雑さ 複数ファイルに分散 pyproject.toml に集約 注意: Ruff は型チェッカーを置き換えるものではありません。Ruff が提供するのは、リント(コード品質チェック)とフォーマットのみです。型安全性を確保したいプロジェクトでは、mypy や pyright などの型チェッカーを別途追加することを強く推奨します。 mypy を使うことで、以下のメリットが得られます: バグの早期発見 : 実行前に型の不整合を検出 リファクタリング安全性 : 型情報を元に安全にコード変更 ドキュメント効果 : 型ヒントが生きたドキュメントに IDE サポート強化 : より正確なコード補完と型推論 セットアップ手順 それでは、実際にこの環境を使ってみましょう。セットアップは驚くほど簡単です! 前提条件 Visual Studio Code Docker Desktop Dev Containers 拡張機能 手順 1. リポジトリのクローン git clone https://github.com/Ryunosuke-Tanaka-sti/uv-single-devcontianer.git cd uv-single-devcontianer 2. DevContainer で開く VS Code でフォルダを開く コマンドパレット(Ctrl+Shift+P / Cmd+Shift+P) 「Dev Containers: Reopen in Container」を選択 3. 自動セットアップ完了 コンテナが起動すると、 uv sync が自動実行され、依存関係がインストールされます。初回は数分かかりますが、2 回目以降はキャッシュが効いて数秒で起動します。 4. Streamlit アプリを実行 uv run streamlit run src/main.py http://localhost:8501 にアクセスすると、データ分析デモアプリが起動します! ディレクトリ構成 リポジトリをクローンすると、以下のような構成になっています。シンプルで分かりやすい構成ですね。 uv-single-devcontianer/ ├── .devcontainer/ │ ├── Dockerfile # 開発環境のDockerイメージ定義 │ └── devcontainer.json # VS Code DevContainer設定 ├── src/ │ └── main.py # Streamlitアプリケーション(サンプル) ├── pyproject.toml # Pythonプロジェクト設定(uv + Ruff設定) ├── uv.lock # uvの依存関係ロックファイル ├── README.md # プロジェクト説明 └── .gitignore # Git除外設定 各ファイルの役割: .devcontainer/ : DevContainer 関連の設定ファイルを格納 src/ : アプリケーションコードを配置(今回は Streamlit のサンプル) pyproject.toml : プロジェクトの依存関係と Ruff 設定を記述 uv.lock : 依存関係のバージョンを固定(再現性確保) この構成は、Streamlit 以外のプロジェクトにも応用できます。例えば、FastAPI や Flask など、別のフレームワークを使う場合でも、 pyproject.toml の dependencies を変更するだけで対応可能です。 設定ファイル解説 ここからは、各設定ファイルの詳細を見ていきます。コードは全文掲載しているので、コピペして使ってください。 Dockerfile FROM python:3.12-slim # 必要最小限のシステムパッケージをインストール RUN apt-get update \ && apt-get install -y --no-install-recommends \ git \ curl \ && rm -rf /var/lib/apt/lists/* # uvのインストール(公式スクリプト使用) RUN curl -LsSf https://astral.sh/uv/install.sh | sh \ && mv /root/.local/bin/uv /usr/local/bin/uv WORKDIR /workspace # Streamlit用のポートを公開 EXPOSE 8501 ポイント解説: python:3.12-slim : Debian ベースの軽量 Python イメージ(119MB) --no-install-recommends : 推奨パッケージを除外して軽量化 rm -rf /var/lib/apt/lists/* : apt キャッシュを削除してサイズ削減 uv は公式スクリプトで最新版を自動取得 devcontainer.json { "name": "Python Dev (uv + Ruff + mypy)", "build": { "dockerfile": "Dockerfile" }, "features": { "ghcr.io/devcontainers/features/common-utils:2": { "username": "vscode", "userUid": "automatic", "userGid": "automatic", "installZsh": false } }, "remoteUser": "vscode", "forwardPorts": [8501], "customizations": { "vscode": { "extensions": ["charliermarsh.ruff", "ms-python.python"], "settings": { "": { "editor.defaultFormatter": "charliermarsh.ruff", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll.ruff": "explicit", "source.organizeImports.ruff": "explicit" } }, "ruff.nativeServer": true, "python.linting.mypyEnabled": true, "python.linting.enabled": true, "python.analysis.typeCheckingMode": "basic" } } }, "postCreateCommand": "uv sync" } ポイント解説: features : vscode ユーザーを自動作成(UID/GID はホストと一致) editor.formatOnSave : ファイル保存時に自動フォーマット source.fixAll.ruff : Ruff のリント修正を自動適用 python.linting.mypyEnabled : mypy による型チェックを有効化 python.analysis.typeCheckingMode : Pylance の型チェックモードを設定 postCreateCommand : コンテナ作成時に依存関係を自動インストール pyproject.toml [project] name = "my-streamlit-project" version = "0.1.0" requires-python = ">=3.12" dependencies = [ "streamlit>=1.39.0", "pandas>=2.2.0", "numpy>=2.0.0", "matplotlib>=3.10.7", ] [dependency-groups] dev = [ "ruff>=0.7.0", "pytest>=8.0.0", "mypy>=1.18.2", ] [tool.ruff] line-length = 88 target-version = "py312" [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "N", # pep8-naming "UP", # pyupgrade "B", # flake8-bugbear ] ignore = [] [tool.ruff.lint.isort] known-first-party = ["my_project"] [tool.ruff.format] quote-style = "double" indent-style = "space" [tool.mypy] python_version = "3.12" warn_return_any = true warn_unused_configs = true disallow_untyped_defs = false check_untyped_defs = true ignore_missing_imports = true Ruff 設定のポイント: line-length = 88 : Black と同じ行長(推奨) select : 有効にするルールセット(PEP 8 準拠) quote-style = "double" : ダブルクォート使用 設定が 1 ファイルに集約されてシンプル mypy 設定のポイント: python_version = "3.12" : Python 3.12 の型システムを使用 warn_return_any = true : Any 型の返り値に警告 disallow_untyped_defs = false : 型ヒントなし関数も許可(段階的導入向け) check_untyped_defs = true : 型ヒントなし関数も内部チェック ignore_missing_imports = true : サードパーティライブラリの型スタブがなくてもエラーにしない 型チェックを実行するには: # mypy で型チェック実行 uv run mypy src/ # VS Code では保存時に自動チェック 2 環境の徹底比較 最後に、2 つの環境パターンを比較してみましょう。 項目 Microsoft 公式 今回(uv + Ruff + mypy) イメージサイズ 1.63GB 273MB ツール統合 Black, Flake8 等(3 つ) Ruff 1 つ 型チェック 手動セットアップ mypy 統合済み 実行速度 通常 10-100 倍高速 セットアップ 簡単 簡単 カスタマイズ性 低い 高い 選択の指針: すぐ使いたい → Microsoft 公式イメージ : プリインストール済みで設定不要 軽量・高速重視 → 今回の環境 : バランスが良く、実用性が高い 今回の環境は、 軽量性と実用性のバランス が取れているため、多くのプロジェクトで活用できると思います。 まとめ 今回は、uv + Ruff + mypy で統一した Python 開発環境を構築し、以下の成果を得ることができました: イメージサイズ 83%削減 (1.63GB → 273MB) ツールを 3 つから 1 つに統合 (Black + Flake8 + isort → Ruff) 実行速度 10-100 倍高速化 (Rust ベースの恩恵) 設定がシンプルに (pyproject.toml 内で完結) 型チェック統合 (mypy で型安全性を確保) 前回の記事で構築した uv 環境をさらに最適化し、軽量・高速・シンプル・型安全の四拍子が揃った開発環境になりました。Astral 社のツール(uv + Ruff)で統一し、mypy で型安全性を追加することで、実用的かつ堅牢な開発環境を実現しています。 注意事項: この環境は開発用途を想定しています。本番環境での使用には、追加のセキュリティ対策が必要です。型チェックの厳格さは、プロジェクトの要件に応じて pyproject.toml で調整できます 本番環境への展開を検討されている方へ 今回構築した開発環境は、 開発体験の向上 に焦点を当てています。本番環境(Production)にデプロイする際は、以下の追加対策が必要になります: セキュリティ対策 non-root ユーザーでの実行 : コンテナを root 以外のユーザーで実行 脆弱性スキャン : Trivy 等のツールでイメージをスキャン 多段階ビルド : ビルドツールと実行環境を分離してさらに軽量化 CI/CD パイプライン統合 GitHub Actions / GitLab CI : 自動テスト・型チェック・デプロイ 自動リント・型チェック : Pull Request 時の自動チェック イメージレジストリへの push : Docker Hub / GitHub Container Registry への自動デプロイ これらの本番環境向け設定については、 次回の記事で詳しく解説予定 です。多段階ビルドによる本番用 Dockerfile の作成方法や、GitHub Actions を使った CI/CD パイプラインの構築手順を、実際に動くサンプルとともにお届けします! 続編記事もお楽しみに! リポジトリは公開しているので、ぜひクローンして試してみてください。Streamlit 以外のプロジェクトでも、 pyproject.toml の dependencies を変更するだけで利用できます。 皆さんも、ぜひ軽量で高速な Python 開発環境を体験してみてください! リポジトリ: https://github.com/Ryunosuke-Tanaka-sti/uv-single-devcontianer.git 前回記事: DevContainer と uv で構築する爆速 Python 開発環境 参考リンク この記事で紹介したツールの公式ドキュメントとリポジトリをまとめました。さらに詳しく知りたい方はこちらをご参照ください。 開発ツール uv(パッケージマネージャー) 公式ドキュメント : https://docs.astral.sh/uv/ GitHub リポジトリ : https://github.com/astral-sh/uv 説明 : Rust で書かれた超高速 Python パッケージマネージャー。pip、pip-tools、poetry、pyenv などを 1 つに統合。 Ruff(リンター・フォーマッター) 公式ドキュメント : https://docs.astral.sh/ruff/ フォーマッター解説 : https://docs.astral.sh/ruff/formatter/ GitHub リポジトリ : https://github.com/astral-sh/ruff 説明 : Rust で実装された超高速リンター・フォーマッター。Black、Flake8、isort などの機能を統合し、10-100 倍の速度を実現。 mypy(型チェッカー) 公式ドキュメント : https://mypy.readthedocs.io/ 公式サイト : https://www.mypy-lang.org/ GitHub リポジトリ : https://github.com/python/mypy 説明 : Python の静的型チェッカー。型ヒントを使ってコードの型安全性を確保。 開発環境 VS Code Dev Containers 公式ドキュメント : https://code.visualstudio.com/docs/devcontainers/containers チュートリアル : https://code.visualstudio.com/docs/devcontainers/tutorial 説明 : Docker コンテナを完全な開発環境として使用できる VS Code の拡張機能。 アプリケーションフレームワーク Streamlit 公式ドキュメント : https://docs.streamlit.io/ 公式サイト : https://streamlit.io/ GitHub リポジトリ : https://github.com/streamlit/streamlit 説明 : Python でインタラクティブなデータアプリを数行のコードで作成できるフレームワーク。 その他の参考資料 Docker 公式 Python イメージ : https://hub.docker.com/_/python 説明 : 今回使用した python:3.12-slim などの公式 Python Docker イメージ。 PEP(Python Enhancement Proposals) PEP 484(型ヒント) : https://peps.python.org/pep-0484/ 説明 : Python の型ヒント仕様。mypy などの型チェッカーの基礎となる規格。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post uv + Ruff + mypyで構築する超軽量Python開発環境 – イメージサイズ削減・型安全性確保を実現 first appeared on SIOS Tech. Lab .
アバター