HubSpot CLI の全コマンドと設定・複数ポータルの管理戦略・ローカル開発の進め方・GitHub Actions による CI/CD パイプライン・チーム開発のベストプラクティスまで。プロジェクトを安全・高速に運用するための体系を整理します。
HubSpot CLI(コマンドラインインターフェース)は、 ローカルのファイルシステムとHubSpotポータルを双方向に同期するツールです。 デザインマネージャーをブラウザ上で操作するより、 エディタとターミナルで高速に開発できるのが最大のメリットです。
HubSpot CLI v8.0.0(2026年2月9日〜有効)より、最低 Node.js バージョンが Node 20 に引き上げられました。
Node 18 は HubSpot サーバーレス関数・CLI 両方で 2025年10月1日にサポート終了済みです。
nvm(Node Version Manager)を使っている場合は nvm install 20 && nvm use 20 で切り替えてください。
また v8 では 旧コマンド(hs upload/hs watch など)が完全削除され、
hs cms upload/hs cms watch への移行が必須です(Section 9-2 参照)。
# Node.js 20以上が必要(v8.0.0以降は必須)。バージョン確認 $ node --version v20.x.x ← 20以上であること(18.x は NG) # npmでHubSpot CLIをグローバルインストール $ npm install -g @hubspot/cli # インストール確認(v8.0.0以上を推奨) $ hs --version 8.x.x # または npx で都度実行(インストール不要) $ npx @hubspot/cli --version
# プロジェクトルートで初期化 $ hs init # 対話形式で設定が進む ? Enter a name for this account (e.g. "my-sandbox"): my-company-dev ? Enter your HubSpot portal ID: 12345678 ? How would you like to authenticate your account? ❯ Personal Access Key (recommended) OAuth2 # Personal Access Key を選択すると、ブラウザが開き # HubSpot管理画面で Personal Access Key を発行できる # Developer Accounts → アカウント → Personal Access Keys から取得 ? Enter your personal access key: eu1-xxxx-xxxx-xxxx-xxxx ✔ Authenticated account: my-company-dev (12345678) ✔ Config file created: ~/.config/@hubspot/cli/config.yml
hs init を実行すると、プロジェクトルートに
hubspot.config.yml が生成されます。
このファイルがCLIの設定の起点になります。
defaultPortal: my-company-dev portals: - name: my-company-dev portalId: 12345678 authType: personalaccesskey personalAccessKey: eu1-xxxx-xxxx-xxxx-xxxx auth: tokenInfo: accessToken: CJa... expiresAt: '2024-12-31T00:00:00.000Z'
hubspot.config.yml には Personal Access Key(アクセストークン)が含まれます。
絶対に Git リポジトリにコミットしてはいけません。
プロジェクト作成直後に .gitignore に追加し、
チームメンバーには各自で hs init を実行してもらいます。
本番CI/CD環境では環境変数経由でトークンを渡す設計にします(後述)。
2025年10月より CMS 関連コマンドが hs cms ネームスペース に移動しました。
CLI v8.0.0 では旧コマンド(hs upload、hs watch 等)が完全削除されています。
CI/CD パイプラインや package.json の scripts に旧コマンドが残っている場合は早急に更新が必要です。
下表で新旧対応を確認してください。
| 旧コマンド(v8で削除済み) | 新コマンド(現在の正式コマンド) | 用途 |
|---|---|---|
| hs upload | hs cms upload | ファイル・ディレクトリをHubSpotにアップロード |
| hs watch | hs cms watch | 変更を監視して自動アップロード(開発中に常時使う) |
| hs fetch | hs cms fetch | HubSpotからローカルにファイルをダウンロード |
| hs lint | hs cms lint | HubL構文チェック |
| hs list | hs cms list | HubSpot上のファイル一覧表示 |
| hs mv | hs cms mv | HubSpot上のファイル移動・リネーム |
| hs remove | hs cms delete | HubSpot上のファイル・フォルダ削除 |
| hs create theme | hs cms app / npx create-cms-theme | テーマ雛形の生成 |
| hs create module | hs cms module | カスタムモジュール雛形生成 |
| hs theme preview | hs cms theme preview | テーマのプレビュー起動 |
| hs theme marketplace-validate | hs cms theme marketplace-validate | マーケットプレイス向けバリデーション |
| hs function ... | hs cms function ... | サーバーレス関数の操作全般 |
| hs logs | hs cms function logs | サーバーレス関数のログ確認 |
# ===== テーマ全体のアップロード ===== $ hs cms upload ./src/my-theme @my-theme --portal=my-company-dev # ===== 開発中のwatchモード起動 ===== $ hs cms watch ./src/my-theme @my-theme --portal=my-company-dev Watcher started, watching "./src/my-theme" Uploaded "templates/page.html" to "@my-theme/templates/page.html" Uploaded "modules/hero-banner.module/module.html" # ===== HubSpotから最新を取得(差分確認前)===== $ hs cms fetch @my-theme ./src/my-theme-remote --portal=my-company-prod --overwrite # ===== デプロイ前の lint チェック ===== $ hs cms lint ./src/my-theme --portal=my-company-dev ✔ No lint errors found # ===== 特定のファイルのみアップロード ===== $ hs cms upload ./src/my-theme/modules/hero-banner.module @my-theme/modules/hero-banner.module # ===== 新しいモジュールの雛形生成 ===== $ hs cms module pricing-table --path=./src/my-theme/modules ✔ Created "pricing-table.module" at ./src/my-theme/modules/pricing-table.module # ===== ポータルのファイル一覧確認 ===== $ hs cms list --portal=my-company-prod @my-theme/ ├── templates/ ├── modules/ ├── css/ ├── js/ └── theme.json
$ hs cms lint ./src/my-theme ✖ Error in "templates/blog-post.html" line 42: Unexpected tag: endmodule (did you mean end_module?) ⚠ Warning in "modules/card-grid.module/module.html" line 18: Variable "module.subtitle" used but not defined in fields.json Lint complete: 1 error, 1 warning # エラーを修正後に再実行 $ hs cms lint ./src/my-theme ✔ No lint errors found (1 warning)
実務での開発は hs cms watch を起動した状態でエディタを使います。
ファイルを保存するたびに自動でHubSpotにアップロードされ、
ブラウザをリロードすれば即座に確認できます。
my-project/ ├── src/ # ← CLIで同期するファイル群 │ └── my-theme/ # テーマ本体 │ ├── theme.json │ ├── templates/ │ ├── modules/ │ ├── css/ │ ├── js/ │ └── images/ ├── .gitignore ├── .hsignore # CLIが無視するファイルを定義 ├── hubspot.config.yml # 認証設定(.gitignoreに追加) ├── package.json # npm scripts で開発コマンドを定義 └── README.md # セットアップ手順のドキュメント
{
"name": "my-company-hubspot",
"version": "1.0.0",
"scripts": {
// ===== 開発コマンド =====
"dev": "hs cms watch src/my-theme @my-theme --portal=dev",
// npm run dev で watch モード起動(devポータルに同期)
// ===== デプロイコマンド =====
"deploy:dev" : "hs cms upload src/my-theme @my-theme --portal=dev --overwrite",
"deploy:prod" : "hs cms upload src/my-theme @my-theme --portal=prod --overwrite",
// ===== チェックコマンド =====
"lint" : "hs cms lint src/my-theme --portal=dev",
"fetch:prod" : "hs cms fetch @my-theme src/my-theme-remote --portal=prod --overwrite",
// ===== 複合コマンド =====
"predeploy:prod": "npm run lint"
// deploy:prodの前にlintを自動実行(エラーがあればデプロイを中断)
},
"devDependencies": {
"@hubspot/cli": "^8.0.0"
// CLI v8以上を指定(Node.js 20必須)
}
}
# === 毎日の開発開始時 === $ npm run dev Watcher started, watching "src/my-theme" # エディタでファイルを編集 → 保存 → 自動アップロード → ブラウザでリロード確認 # === 作業が終わったら watch を Ctrl+C で停止 === # === 本番デプロイ前のチェック === $ npm run lint ✔ No lint errors found # === 本番デプロイ(lintが通った場合のみ実行される)=== $ npm run deploy:prod Uploading "src/my-theme" to "@my-theme" on portal "prod"... ✔ Done uploading 48 files
実案件では開発用ポータル(Sandbox/Developer Account)と 本番ポータルを分離して管理します。 本番環境に直接 watch することは事故の原因になるため厳禁です。
# デフォルトポータル(hs cms upload で --portal を省略した場合に使われる) defaultPortal: dev portals: # ===== 開発ポータル(日常開発用)===== - name: dev portalId: 11111111 authType: personalaccesskey personalAccessKey: eu1-dev-key-xxxxxxxxxx # ===== 本番ポータル(デプロイ時のみ)===== - name: prod portalId: 22222222 authType: personalaccesskey personalAccessKey: eu1-prod-key-xxxxxxxxxx # ===== クライアント検証用(任意)===== - name: staging portalId: 33333333 authType: personalaccesskey personalAccessKey: eu1-staging-key-xxxxxxxxxx
| ポータル | 使用場面 | watch の使用 | 管理画面編集 |
|---|---|---|---|
| 開発ポータル(dev) | 日常的な開発・動作確認 | ✅ 推奨 | 自由に可 |
| ステージング(staging) | クライアントへの確認依頼・QA | ⚠️ 慎重に | 限定的に |
| 本番ポータル(prod) | 最終デプロイのみ | 🚫 禁止 | 原則禁止 |
hs cms watch を本番ポータルに向けて起動すると、
開発中の未完成なコードが即座に本番に反映されてしまいます。
本番へのアップロードは必ず hs cms upload コマンドで手動実行し、
デプロイ内容を意識的に確認してから行ってください。
package.json の dev スクリプトが常に開発ポータルを向いているか定期的に確認する習慣をつけましょう。
.hsignore ファイルは .gitignore と同じ形式で、
hs cms upload や hs cms watch で同期しないファイル・ディレクトリを指定します。
*.md を .hsignore に入れておくと、
README.md や CHANGELOG.md といったドキュメントファイルがHubSpotにアップロードされません。
同様に package.json や node_modules/ も ignore することで、
HubSpot上のファイル構成をクリーンに保てます。
hubspot.config.yml には認証情報以外にも、
CLIの動作を細かくカスタマイズするオプションがあります。
defaultPortal: dev # ===== CLIのグローバル設定 ===== httpTimeout: 30000 # APIリクエストのタイムアウト時間(ミリ秒) # 大きなテーマをアップロードする際はこの値を増やす allowUsageTracking: false # HubSpotへの使用状況データ送信の許否 portals: - name: dev portalId: 11111111 authType: personalaccesskey personalAccessKey: eu1-dev-key # ===== ポータル個別設定 ===== defaultMode: write # write(アップロード優先)/ read(ダウンロード優先) - name: prod portalId: 22222222 authType: personalaccesskey personalAccessKey: eu1-prod-key defaultMode: write
Git リポジトリと GitHub Actions を連携させることで、 「mainブランチにマージされたら自動で本番デプロイ」 という CI/CD パイプラインを構築できます。
Personal Access Key を GitHub リポジトリの Secrets に登録します。 GitHub のリポジトリページ → Settings → Secrets and variables → Actions から設定します。
| Secret 名 | 値 |
|---|---|
| HUBSPOT_PORTAL_ID_DEV | 開発ポータルのポータルID |
| HUBSPOT_ACCESS_KEY_DEV | 開発ポータルの Personal Access Key |
| HUBSPOT_PORTAL_ID_PROD | 本番ポータルのポータルID |
| HUBSPOT_ACCESS_KEY_PROD | 本番ポータルの Personal Access Key |
name: Deploy to Dev Portal on: push: branches: - develop jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - name: Install HubSpot CLI run: npm install -g @hubspot/cli - name: Create HubSpot config # Secretsから hubspot.config.yml を動的生成 run: | cat > hubspot.config.yml << EOF defaultPortal: dev portals: - name: dev portalId: ${{ secrets.HUBSPOT_PORTAL_ID_DEV }} authType: personalaccesskey personalAccessKey: ${{ secrets.HUBSPOT_ACCESS_KEY_DEV }} EOF - name: Lint check run: hs cms lint src/my-theme --portal=dev - name: Deploy to Dev run: hs cms upload src/my-theme @my-theme --portal=dev --overwrite - name: Notify Slack on success if: success() uses: slackapi/slack-github-action@v1 with: payload: | { "text": "✅ 開発環境へのデプロイ完了: ${{ github.event.head_commit.message }}" } env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
name: Deploy to Production on: push: branches: - main jobs: lint: name: Lint Check runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: '20' } - run: npm install -g @hubspot/cli - name: Create config run: | cat > hubspot.config.yml << EOF defaultPortal: dev portals: - name: dev portalId: ${{ secrets.HUBSPOT_PORTAL_ID_DEV }} authType: personalaccesskey personalAccessKey: ${{ secrets.HUBSPOT_ACCESS_KEY_DEV }} EOF - run: hs cms lint src/my-theme --portal=dev deploy: name: Deploy to Production needs: lint # lint job が成功した場合のみ実行 runs-on: ubuntu-latest environment: production # GitHub Environments で承認ゲートを設定可能 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: '20' } - run: npm install -g @hubspot/cli - name: Create production config run: | cat > hubspot.config.yml << EOF defaultPortal: prod portals: - name: prod portalId: ${{ secrets.HUBSPOT_PORTAL_ID_PROD }} authType: personalaccesskey personalAccessKey: ${{ secrets.HUBSPOT_ACCESS_KEY_PROD }} EOF - name: Deploy to Production run: hs cms upload src/my-theme @my-theme --portal=prod --overwrite - name: Notify on success if: success() uses: slackapi/slack-github-action@v1 with: payload: | { "text": "🚀 本番デプロイ完了!\ncommit: ${{ github.event.head_commit.message }}\nby: ${{ github.actor }}" } env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - name: Notify on failure if: failure() uses: slackapi/slack-github-action@v1 with: payload: | { "text": "❌ 本番デプロイ失敗!確認が必要です。\n${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" } env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
GitHub の Settings → Environments で production 環境を作成し、
Required reviewers(承認者)を設定すると、
main へのマージ後・デプロイ実行前に指定メンバーの承認が必要になります。
ワークフローの environment: production がこれと連動します。
意図しない本番デプロイを防ぐ安全装置として非常に有効です。
2026年2月19日、HubSpot Developer MCP Server が正式GA(一般公開)されました。 MCP(Model Context Protocol)は、AIツールが外部サービスと連携するための標準規格です。 HubSpot の Developer MCP Server をローカルにインストールすることで、 VS Code・Claude Code・Cursor などのAIエディタが HubSpot の開発者ドキュメントを参照しながら、自然言語でCMSアセットの生成・デプロイ・デバッグを実行できるようになります。
CLIを通じてインストールし、ローカルで動作するサーバー。HubSpotの開発者プラットフォームに接続し、プロジェクトのスキャフォールド・CMS資産の管理・サーバーレス関数のデバッグを自然言語で実行できる。CLI v8.0.0以上・Platform v2025.2が必要。
mcp.hubspot.comに接続するリモートサーバー。HubSpot CRMデータへのリアルタイムアクセスを提供し、「このコンタクトの最新アクティビティを取得して」などのクエリに対応。OAuth 2.0認証を使用。
# 前提:CLI v8.0.0以上がインストール済みであること $ hs --version 8.x.x # MCP Server をセットアップ(対話形式) $ hs mcp setup # ↓ 対話式で接続するMCPクライアントを選択 ? Which clients would you like to add the MCP server to? ❯ ◉ VS Code ◉ Claude Code ◯ Cursor ◯ OpenAI Codex (Use arrow keys and spacebar to select, Enter to proceed) ✔ HubSpotDev MCP server has been added to: VS Code, Claude Code Restart your client to apply the changes.
| タスク | AIへのプロンプト例 |
|---|---|
| モジュール生成 | 「pricing-tableというReactモジュールを作って。価格プラン3列を表示するグリッドレイアウトで、各列にタイトル・価格・特徴リストを表示できるフィールド設計にして」 |
| テンプレート生成 | 「Product Landingというページテンプレートを新規作成して。ヒーローセクション・特徴グリッド・CTAセクションの3ブロック構成で、全てdnd_area対応にして」 |
| エラーデバッグ | 「NewCard.tsxでローカル開発中に 'Unable to initialize extension' エラーが出ている。ファイルを確認して修正案を提示して」 |
| CLIの使い方確認 | 「HubSpot CLIのv8で削除されたコマンドと、その代替コマンドを教えて」 |
| デプロイ | 「変更を確認したらdevポータルにアップロードして」 |
| サーバーレス関数 | 「POST /api/submit-form のエンドポイントを持つサーバーレス関数を生成して、フォームデータをHubSpot CRMに登録するロジックも含めて」 |
最も効果が高い使い方は「モジュール・テンプレートの初期スキャフォールド」です。
フィールド設計の雛形生成・サーバーレス関数のボイラープレート生成など、
繰り返し作業をAIに委ねることで開発速度が大きく上がります。
なお、HubSpotドキュメントには 「Claude Sonnet 4 以上を使うと最も安定した結果が得られる」 と記載されています。
MCPサーバーとClaude Codeの組み合わせが現時点での推奨構成です。
注意点:MCPサーバーは Developer Platform v2025.2 が必要です。
古いプロジェクトは hs project migrate コマンドで移行してください(サーバーレス関数を含む場合は手動移行が必要)。
HubSpotのデザインマネージャーにはバージョン履歴機能があり、 各ファイルの変更履歴から過去のバージョンに戻せます。 ただし、CLIによる一括アップロードではすべてのファイルが上書きされるため、 「Gitタグ + hs cms upload」によるバージョン管理が安全なロールバック手段になります。
# === 本番デプロイ時は必ずGitタグを打つ === $ git tag v1.2.0 -m "ヒーローバナーリニューアル" $ git push origin v1.2.0 # === デプロイ後に問題が発覚した場合のロールバック === # ① ロールバックしたいバージョンのタグをチェックアウト $ git checkout v1.1.0 HEAD is now at abc1234 v1.1.0 # ② 旧バージョンのファイルを本番にアップロード $ hs upload src/my-theme @my-theme --portal=prod --overwrite ✔ Rollback complete: v1.1.0 deployed to production # ③ 作業ブランチに戻る $ git checkout main # ④ 問題のある変更を修正してから再デプロイ
# my-company-hubspot ## 前提条件 - Node.js 20以上(CLI v8.0.0以降必須) - @hubspot/cli グローバルインストール - 開発ポータルへのアクセス権(ポータルIDは別途共有) ## セットアップ手順 ### 1. リポジトリをクローン git clone https://github.com/mycompany/hubspot-theme.git cd hubspot-theme ### 2. HubSpot CLIの認証設定 hs init # 開発ポータルID: 12345678 (別途Slackで共有) # Personal Access Key: HubSpot管理画面から各自で発行 # https://app.hubspot.com/personal-access-key/12345678 ### 3. 必要なスコープ(Personal Access Keyの発行時に選択) # ✅ CMS - Design Manager # ✅ Content ### 4. 開発開始 npm run dev # ブラウザで開発ポータルを開き、編集内容を確認 # https://app.hubspot.com/website-pages/12345678 ## ブランチ戦略 # feature/xxx → develop(DEVポータルに自動デプロイ) # develop → main(本番ポータルに自動デプロイ)
| スコープ | 必要な操作 |
|---|---|
| CMS - Design Manager | テンプレート・モジュール・テーマのアップロード・ダウンロード(必須) |
| Content | ページ・ブログ記事の閲覧・編集(テンプレート確認に必要) |
| HubDB | HubDBテーブルの操作(HubDBを使う場合) |
| Forms | フォームの確認・テスト(フォーム開発に必要) |
複数の開発者やマーケターが同時に作業していると、
管理画面からの直接編集と CLI からのアップロードが競合する場合があります。
対処法:
① CLIからのデプロイは常に --overwrite フラグを付けて実行する。
② 管理画面での直接編集は禁止し、変更は必ずローカルコードを通す運用ルールを作る。
③ もし管理画面側で重要な変更がされてしまった場合は、hs cms fetch で取得してローカルに取り込み、コードを更新してからアップロードする。
④ チャット(Slack等)で「今デプロイします」の声がけを行い、同時デプロイを防ぐ。
.src、リンクフィールドは .url で存在チェックしているか。
get_asset_url() を通しているか。
loading="eager"、その他には loading="lazy" が付いているか。
{{ standard_footer_includes }} が含まれているか。
Personal Access Key には有効期限はありませんが、 セキュリティ上、6ヶ月〜1年ごとに定期ローテーションを推奨します。 チームメンバーが退職した場合は即時無効化してください。 GitHub Secrets の更新も忘れずに行います。
2026年2月9日よりCLI v8.0.0が有効。Node.js 20以上が必須で、hs upload等の旧コマンドは完全削除。全て hs cms upload / hs cms watch 等の新体系に移行する。
2026年2月GAのHubSpot Developer MCP Serverで、VS CodeやClaude Codeから自然言語でモジュール生成・デプロイ・デバッグが可能に。CLI v8 + Platform v2025.2が前提。
開発・本番の2ポータル分離が基本。hs cms watch は開発ポータル専用。本番へのアップロードは hs cms upload で明示的に実行し、GitHub Actions で自動化する。
Personal Access Keyが含まれるため必ず .gitignore に追加。CI/CDでは環境変数経由でトークンを渡し、動的にymlを生成する。
develop push → 開発ポータルへ自動デプロイ、main push → 本番ポータルへ自動デプロイ。デプロイ前に hs cms lint を必ず通す。GitHub Deploy Action は v1.7 以上を使用。
管理画面での直接編集を禁止し、変更は必ずローカルコードを通す。デプロイ前にSlack等で声がけ。競合が起きた場合は hs cms fetch でリモートを取得してから解決する。