solo-deploy について
ビルド完了後のプロジェクトを対象とするデプロイスキルです。スタックテンプレートや設定を読み、利用可能な CLI を確認してデプロイを準備し、公開状態を検証します。
主な機能
- 01スタックテンプレートとプロジェクト情報の読み込み
- 02インストール済みデプロイ CLI の検出
- 03デプロイ条件とプロジェクト種別の確認
- 04データベースと環境変数の準備
- 05デプロイと公開状態の検証
活用シーン
- 01完成した Web アプリのデプロイ
- 02CLI やライブラリのパッケージレジストリへの公開
- 03ローカル専用と指定されたプロジェクトのデプロイ省略
MCP 対応
過去のデプロイ検索、プロジェクトコードの検索、依存関係やスタックの照会に MCP ツールを利用できます。利用できない場合は、ファイル検索と読み込みに切り替えます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ fortunto2/ solo-factory --skill solo-deployインストール後、Claude Code で/solo-deployを入力して読み込まれたか確認します。
同梱ファイルreferences/platform-commands.md
詳細
/deploy
プロジェクトをホスティングプラットフォームにデプロイします。スタックテンプレート YAML(templates/stacks/{stack}.yaml)を読み込み、正確なデプロイ設定(プラットフォーム、CLI ツール、インフラ階層、CI/CD、監視)を確認します。インストール済みの CLI ツールを検出し、データベースと環境をセットアップして、コードをプッシュし、デプロイが稼働中であることを検証します。
ライブコンテキスト
- ブランチ:!
git branch --show-current 2>/dev/null - 未コミット:!
git status --short 2>/dev/null | wc -l | tr -d ' 'ファイル - 最後のコミット:!
git log --oneline -1 2>/dev/null
参考資料
templates/principles/dev-principles.md— CI/CD、シークレット、DNS、共有インフラのルールdev-principles-my.md(存在する場合)— 個人用インフラ拡張(認証、トンネル、監視)templates/stacks/*.yaml— デプロイ、インフラ、ci_cd、monitoring フィールドを含むスタックテンプレート
パスはスキルのプラグインルートからの相対パスです。想定される場所にファイルが見つからない場合は、Glob で検索してください。
使用するタイミング
/build のすべてのタスクが完了した後(ビルド段階の完了後)に実行します。これがデプロイエンジンです。
パイプライン:/build → /deploy → /review
MCP ツール(利用可能な場合に使用)
session_search(query)— 類似プロジェクトが以前どのようにデプロイされたかを検索しますproject_code_search(query, project)— プロジェクト間のデプロイパターンを検索しますcodegraph_query(query)— プロジェクトの依存関係とスタックを確認します
MCP ツールが利用できない場合は、Glob + Grep + Read を使用してください。
デプロイ前チェック
0. デプロイが必要か確認する
docs/workflow.md(存在する場合)を読み込みます。「No deploy」、「no deploy stage」、「ship = commit」のいずれかが含まれている場合:
- 出力:「Deploy skipped — workflow.md says no deploy stage (CLI/local project).」
- 直ちに
<solo:done/>を出力します。 - デプロイ手順を一切進めないでください。
また、プロジェクトにデプロイ用インフラが一切なく(Dockerfile、deploy.sh、wrangler.toml、vercel.json、sst.config.ts のいずれもない)、かつ workflow.md が存在する場合:
- 同様に、デプロイをスキップして完了を出力します。
1. ビルドが完了していることを確認する(任意)
- パイプライン状態の追跡がある場合(
.solo/states/ディレクトリ)、.solo/states/buildを確認します。 .solo/states/が存在するのにbuildマーカーがない場合は、「ビルドが完了していない可能性があります。まず/buildの実行を検討してください。」と警告します。.solo/states/が存在しない場合は、この確認を省略してデプロイに進みます。
2. 利用可能な CLI ツールを検出する
並列で実行し、ローカルにインストール済みのものを検出します:
vercel --version 2>/dev/null && echo "VERCEL_CLI=yes" || echo "VERCEL_CLI=no"
wrangler --version 2>/dev/null && echo "WRANGLER_CLI=yes" || echo "WRANGLER_CLI=no"
npx supabase --version 2>/dev/null && echo "SUPABASE_CLI=yes" || echo "SUPABASE_CLI=no"
fly version 2>/dev/null && echo "FLY_CLI=yes" || echo "FLY_CLI=no"
sst version 2>/dev/null && echo "SST_CLI=yes" || echo "SST_CLI=no"
gh --version 2>/dev/null && echo "GH_CLI=yes" || echo "GH_CLI=no"
cargo --version 2>/dev/null && echo "CARGO_CLI=yes" || echo "CARGO_CLI=no"
利用可能なツールを記録します。見つかったツールは直接使用してください。CLI がグローバルにインストール済みの場合は npx を使用しないでください。
3. プロジェクトのコンテキストを読み込む(並列読み込み)
CLAUDE.md— スタック名、アーキテクチャ、デプロイプラットフォームdocs/prd.md— 製品要件、デプロイに関する注記docs/workflow.md— CI/CD ポリシー(存在する場合)package.jsonまたはpyproject.toml— 依存関係、スクリプトwrangler.toml、sst.config.ts、vercel.json— プラットフォーム設定(存在する場合)docs/plan/*/plan.md— 有効な計画(デプロイ関連のフェーズやタスクを確認)
計画主導のデプロイ: 有効な計画にデプロイフェーズやタスク(例:「Python バックエンドを VPS にデプロイする」、「deploy.sh を実行する」、「サーバーに Docker をセットアップする」)が含まれている場合、それらを主要なデプロイ手順として扱います。計画には、汎用スタック YAML では網羅されていない、プロジェクト固有のデプロイ先が記載されている可能性があります。標準的なプラットフォームへのデプロイに加えて(またはその代わりに)、計画に記載されたデプロイタスクを実行してください。
3b. プロジェクトの種類を検出する
適切なデプロイ戦略を選択するため、プロジェクトを分類します。
| シグナル | プロジェクトの種類 | デプロイ先 |
|---|---|---|
package.json + next.config.* | Web(Next.js) | Vercel / CF Pages |
wrangler.toml | Web(Workers) | Cloudflare Workers |
Cargo.toml + [lib] のみ | ライブラリ(Rust クレート) | crates.io |
Cargo.toml + [[bin]] のみ | CLI/TUI ツール | crates.io + GitHub Releases |
Cargo.toml + [[bin]] + [lib] | ライブラリ + CLI | crates.io + GitHub Releases |
pyproject.toml + [project.scripts] | CLI(Python) | PyPI |
pyproject.toml(scripts なし、Web ではない) | ライブラリ(Python) | PyPI |
*.xcodeproj | iOS アプリ | App Store → /solo:ios-release |
build.gradle.kts + com.android.application | Android アプリ | Play → /solo:android-release |
CLI/TUI/ライブラリのプロジェクトの場合: Web のデプロイ手順(Vercel、CF など)は省略し、パッケージレジストリへのデプロイ(crates.io、PyPI、npm)に直接進みます。
3c. クロスコンパイル互換性チェック(Rust/ネイティブプロジェクト)
対象: Cargo.toml が存在し、CI/CD が異なるアーキテクチャでビルドする場合(例:GitHub Actions の x86_64 とローカルの Apple Silicon)。
# Check for native/system dependencies that may fail cross-compile
grep -r 'links\s*=' Cargo.toml 2>/dev/null # C library bindings
grep -r 'build\s*=' Cargo.toml 2>/dev/null # build.rs (may compile C code)
grep -rn 'sys' Cargo.toml 2>/dev/null | grep -v '#' # *-sys crates (native bindings)
既知のクロスコンパイルのリスク:
ort-sys/onnxruntime-sys— すべてのターゲット向けのビルド済みバイナリがなく、ローカルでのビルドが必要ですffmpeg-sys/ffmpeg-next— CI ランナーに FFmpeg がインストールされている必要がありますopenssl-sys— 純 Rust 製の TLS を使用するには、代わりにrustlsを使います- その他の
*-sysクレート — CI のターゲットアーキテクチャ向けのビルド済みバイナリがあるか確認します
リスクのある依存関係が見つかった場合:
- CI マトリックスに必要なターゲットが含まれているか確認します(
.github/workflows/*.yml) - CI にクロスコンパイルツールチェーンを追加するよう推奨します。または
- ネイティブ依存関係を純 Rust 製の代替手段に置き換えるよう推奨します。または
- CI のインストール手順に依存関係を追加します:
apt-get install/brew install - CI を妨げる可能性のある依存関係をデプロイ概要で報告します
4. スタックテンプレート YAML を読み込む
CLAUDE.md からスタック名を抽出します(stack: フィールドまたは技術スタックのセクションを確認します)。
スタックテンプレートを読み込み、正確なデプロイ設定を取得します。
検索順序(最初に見つかったものを使用):
templates/stacks/{stack}.yaml— このスキルのプラグインルートからの相対パス.solo/stacks/{stack}.yaml— ユーザーのローカル上書き設定(/initによる)- Glob で、プロジェクトまたは親ディレクトリ内の
**/stacks/{stack}.yamlを検索します
YAML から次のフィールドを抽出します。
deploy— 対象プラットフォーム:vercel、cloudflare_workers、cloudflare_pages、docker、hetzner、app_store、play_store、localdeploy_cli— CLI ツールとその用途(例:vercel (local preview, env vars, promote))infra— インフラストラクチャツールとティア(例:sst (sst.config.ts) — Tier 1)ci_cd— CI/CD システム(例:github_actions)monitoring— モニタリング/アナリティクス(例:posthog)database/orm— データベースと ORM(ある場合。マイグレーション手順に影響します)storage— ストレージサービス(ある場合。R2、D1、KV など)notes— スタック固有のデプロイに関する注意事項
以下のすべてのデプロイ判断では、YAML の値を信頼できる情報源として使用します。YAML はフォールバックのティアマトリックスより優先されます。
5. プラットフォームを検出する(YAML がない場合のフォールバック)
スタック YAML が見つからない場合は、次のフォールバック表を使用します。
| スタック | プラットフォーム | ティア |
|---|---|---|
nextjs-supabase / nextjs-ai-agents | Vercel + Supabase | Tier 1 |
cloudflare-workers | Cloudflare Workers (wrangler) | Tier 1 |
astro-static / astro-hybrid | Cloudflare Pages (wrangler) | Tier 1 |
python-api | Cloudflare Workers (MVP) または Pulumi + Hetzner (本番環境) | Tier 1/2 |
python-ml | スキップ(CLI ツールのため、ホスティングは不要) | — |
rust-native | crates.io(ライブラリ/CLI クレート)またはバイナリリリース(GitHub Releases) | Tier 1 |
ios-swift | /solo:ios-release に引き継ぎます(App Store / TestFlight) | — |
kotlin-android / kotlin-multiplatform | /solo:android-release に引き継ぎます(Play Console) | — |
$ARGUMENTS でプラットフォームが指定されている場合は、自動検出や YAML よりもその指定を優先します。
自動デプロイ対応プラットフォーム(YAML の deploy フィールドまたはフォールバックから判定):
vercel/cloudflare_pages— プッシュ時に自動デプロイされます。プロジェクトがすでに連携されている場合は、GitHub へのプッシュだけで十分です。初回セットアップ時に限り、手動でデプロイします。cloudflare_workers—wrangler deployが必要です(Workers には Git ベースの自動デプロイはありません)。docker/hetzner— SSH または Pulumi を使って手動でデプロイします。
デプロイ手順
Step 1. Git — クリーンな状態にしてプッシュ
git status
git log --oneline -5
未コミットの変更がある場合は、残りの変更をコミットします。
git add -A
git commit -m "chore: pre-deploy cleanup"
リモートの存在を確認し、プッシュします。
git remote -v
git push origin main
リモートがない場合は、GitHub リポジトリを作成します。
gh repo create {project-name} --private --source=. --push
自動デプロイ対応プラットフォーム(Vercel、CF Pages)の場合: main へのプッシュによって自動的にデプロイが開始されます。プロジェクトがすでに連携されている場合は、手動デプロイのコマンドを省略してください。
Step 2. データベースのセットアップ
Supabase(supabase/ ディレクトリまたは Supabase の依存関係が検出された場合):
# If supabase CLI available:
supabase db push # apply migrations
supabase gen types --lang=typescript --local > db/types.ts # optional: regenerate types
CLI がない場合は、移行のために Supabase ダッシュボードを使うようユーザーに案内します。
Drizzle ORM(drizzle.config.ts が存在する場合):
npx drizzle-kit push # push schema to database
npx drizzle-kit generate # generate migration files (if needed)
D1 (Cloudflare)(wrangler.toml に D1 バインディングがある場合):
wrangler d1 migrations apply {db-name}
データベースがまだ設定されていない場合は、必要な項目を列挙して処理を続けます。そこで止めないでください。
Step 3. 環境変数
.env.example または .env.local.example を読み、必要な変数を特定します。
プラットフォーム固有の手順を生成します。
Vercel:
# If vercel CLI is available and project is linked:
vercel env ls # show current env vars
# Guide user:
echo "Set env vars: vercel env add VARIABLE_NAME"
echo "Or via dashboard: https://vercel.com/[team]/[project]/settings/environment-variables"
Cloudflare:
wrangler secret put VARIABLE_NAME # interactive prompt for value
# Or in wrangler.toml [vars] section for non-secret values
実際のシークレットを含む .env ファイルを作成または変更しないでください。
必要な項目を列挙し、値はユーザーに設定してもらいます。
Step 4. プラットフォームへのデプロイ
プラットフォームごとのデプロイ、環境変数、ログの各コマンドについては、references/platform-commands.md を参照してください。
プリフライトチェックで検出したプラットフォームを使用します。
- Vercel —
vercel link→vercel(プレビュー)→vercel --prod - Cloudflare Workers —
wrangler deploy - Cloudflare Pages —
wrangler pages deploy ./out - SST —
sst deploy --stage prod
自動デプロイ対応プラットフォーム(Vercel、CF Pages)の場合、すでに連携されていれば git push origin main だけで十分です。
Step 4b. Rust/Crates.io へのデプロイ
検出条件: プロジェクトのルートに Cargo.toml が存在し、cargo CLI が利用可能であること。
Cargo.toml に基づいてデプロイ先を判定します。
[lib]セクションがある場合、またはクレートがライブラリの場合 → crates.io に公開[[bin]]のみの場合 → バイナリリリース(GitHub Releases)- 両方ある場合 → 両方実行します(クレートを公開し、バイナリをリリースに添付)
公開前チェックリスト:
# 1. Verify tests + clippy pass
cargo test
cargo clippy --all-targets -- -D warnings
# 2. Check Cargo.toml has required fields for crates.io
grep -E '^(name|version|description|license|repository)' Cargo.toml
# 3. Dry run publish
cargo publish --dry-run
crates.io に必要な Cargo.toml フィールド(不足している場合は失敗します):
name、version、description、license(またはlicense-file)、repository
フィールドが不足している場合は追加してコミットしてから、次に進みます。
crates.io に公開:
# Check if already published at this version
CRATE_NAME=$(grep '^name' Cargo.toml | head -1 | sed 's/.*= *"//' | sed 's/".*//')
CRATE_VER=$(grep '^version' Cargo.toml | head -1 | sed 's/.*= *"//' | sed 's/".*//')
# Publish (requires `cargo login` — if not authenticated, note in report and skip)
cargo publish
公開に失敗した場合:
already uploaded→ そのバージョンはすでに存在します。Cargo.toml のバージョンを上げてください。not logged in→ レポートに「crates.io API トークンを使ってcargo loginを実行してください」と記載します。dependency not on crates.io→ path/git 依存関係を確認し、crates.io のバージョンに置き換えてください。
バイナリリリース(任意。CLI ツール向け):
# Build release binary
cargo build --release
# Create GitHub release with binary attached
BINARY_NAME=$(grep '^name' Cargo.toml | head -1 | sed 's/.*= *"//' | sed 's/".*//')
gh release create "v${CRATE_VER}" --title "v${CRATE_VER}" --generate-notes \
"target/release/${BINARY_NAME}#${BINARY_NAME}-$(uname -s)-$(uname -m)"
crates.io でクレートを確認:
# Wait a few seconds for index to update, then check
curl -s "https://crates.io/api/v1/crates/${CRATE_NAME}/${CRATE_VER}" | head -100
Step 5. デプロイを確認する
デプロイ後、実際に動作することを確認します。
STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://{deployment-url})
BODY=$(curl -s https://{deployment-url} | head -200)
HTTP ステータスが 200 でない場合: 環境変数を確認して修正し、再デプロイします。プラットフォーム固有の環境変数およびエラー解決コマンドについては、references/platform-commands.md を参照してください。
ライブ URL が HTTP 200 を返し、エラーなくページが読み込まれるまで、<solo:done/> を出力しないでください。 問題を解決できない場合は、<solo:redo/> を出力してビルドに戻ります。パイプラインシグナルを出力するのは、.solo/states/ ディレクトリが存在する場合のみです。
Step 6. デプロイ後のログ監視
HTTP 200 を確認したら、本番環境のログを tail して実行時エラーを検出します。プラットフォーム固有のログコマンドと確認事項については、references/platform-commands.md を参照してください。
ログのエラーへの対応:
- 環境変数がない → プラットフォーム CLI で修正し(Step 3 を参照)、再デプロイします
- DB 接続エラー → 接続文字列と IP 許可リストを確認します
- 実行時クラッシュ/未処理エラー →
.solo/states/が存在する場合は、修正してビルドに戻るために<solo:redo/>を出力します。それ以外の場合は修正して再デプロイします - ログの 30 行にエラーがない → レポートに進みます
ログにトラフィックがまったく表示されない場合(新規デプロイ)、テストリクエストをいくつか送信します:
curl -s https://{deployment-url}/ # homepage
curl -s https://{deployment-url}/api/health # API health (if exists)
その後、これらのリクエストによって発生したエラーがないか、ログを再確認します。
Step 7. デプロイ後のレポート
Deployment: {project-name}
Platform: {platform}
URL: {deployment-url}
Branch: main
Commit: {sha}
Done:
- [x] Code pushed to GitHub
- [x] Deployed to {platform}
- [x] Database migrations applied (or N/A)
Manual steps remaining:
- [ ] Set environment variables (listed above)
- [ ] Custom domain (optional)
- [ ] PostHog / analytics setup (optional)
Next: /review — final quality gate
完了
完了を通知する
.solo/states/ ディレクトリが存在する場合は、次のタグを正確に 1 回だけ出力します。パイプラインは最初の出現を検出します。
<solo:done/>
応答内のほかの場所で、このシグナルタグを繰り返し出力しないでください。 出現は 1 回のみです。
.solo/states/ ディレクトリが存在しない場合は、シグナルタグを省略します。
エラー処理
CLI が見つからない
原因: プラットフォーム CLI がインストールされていません。
対処: 該当する CLI をインストールします:npm i -g vercel、npm i -g wrangler、brew install supabase/tap/supabase。
デプロイ失敗 — ビルドエラー
原因: ローカルではビルドできても、プラットフォーム上では失敗します(Node のバージョンの違い、環境変数の不足など)。
対処: プラットフォームのビルドログを確認します。package.json の engines がプラットフォームと一致していることを確認します。不足している環境変数を設定します。
データベース接続の失敗
原因: DATABASE_URL が設定されていないか、ネットワークルールによって接続がブロックされています。 対処: 接続文字列、プラットフォームの DB ダッシュボード、IP 許可リストを確認します。
Git push が拒否された
原因: リモートとの間で履歴が分岐しています。
対処: git pull --rebase origin main を実行し、競合を解決してから、再度 push します。
検証ゲート
「デプロイに成功しました」と報告する前に:
- デプロイ URL に対して
curl -s -o /dev/null -w "%{http_code}"を実行します。 - HTTP 200 であることを確認します(404、500、リダイレクトループではないこと)。
- 実際のページ内容が期待どおりであることを確認します(空白ページやエラーページではないこと)。
- その後に限り、デプロイに成功したと報告します。
「デプロイされているはずです」と決して言わず、実際にデプロイされていることを確認します。
パイプライン/自律モード
パイプライン(--print、人間が監視していない状態)で実行する場合:
- AskUserQuestion は絶対に呼び出さないでください — イテレーション間で応答が失われ、無限の再試行ループにつながります(OpenWok のデプロイでは 5 回のイテレーションが無駄になった事例があります)
- 自律的にデプロイを判断します:
- デプロイ用 CLI がインストールされていない → 可能であれば brew/npm でインストールします。できない場合は Dockerfile と .dockerignore を作成し、コードを push して「手動デプロイの準備完了」とします
- 認証/認証情報がない → すべてのデプロイ設定を作成し、GitHub に push して、認証手順を記載した状態ファイルを書き込み、完了を通知します
- プラットフォームの選択肢が複数ある → 次の基準で選びます:スタック YAML > Next.js/React → Vercel、Python → Cloudflare Workers(MVP)または Hetzner(本番環境)、静的サイト → Cloudflare Pages
- ブロッカーは飛ばします — ブラウザーでのログイン、手動承認、API キーの不足などはレポートに記載し、続行します
- 必ず完了を通知します — 部分的なデプロイ(設定を作成してコードを push)でも、無限に再試行するより望ましいです。実際のデプロイに手動の認証手順が必要な場合でも、
<solo:done/>を出力します。
重要なルール
- インストール済みのCLIを使用する —
npxにフォールバックする前に、vercel、wrangler、supabase、fly、sstがあるか確認してください。 - 自動デプロイを考慮する — プラットフォームがプッシュ時に自動デプロイする場合は、そのままプッシュしてください。不要な手動デプロイコマンドは実行しないでください。
- シークレットは絶対にコミットしない — 実際の値を含む .env ファイルや、コード内の API キーは使用しないでください。
- 本番環境の前にプレビューする — まずプレビュー環境にデプロイして検証し、その後、本番環境に反映してください。
- まずローカルでビルドを確認する — デプロイ前に
pnpm build/uv build(または同等のコマンド)を実行してください。 - 本番環境のログを確認する — デプロイ後は必ずログを継続的に確認し、成功を宣言する前に実行時エラーを検出してください。
- すべてのURLを報告する — デプロイURLとプラットフォームのダッシュボードへのリンクを報告してください。
- インフラストラクチャはリポジトリで管理する — 手動でのダッシュボード設定より、
sst.config.tsやwrangler.tomlを優先してください。 - 完了を宣言する前に検証する — 「デプロイコマンドが成功した」だけでなく、公開URLからの HTTP 200 と、エラーのないログを確認してください。