2025-07-19

tmux で実現する Claude Code 複数エージェント連携システム

tmuxで実現するClaude Code複数エージェント連携システム

動作環境

  • OS: Windows 11 + WSL2 (Ubuntu)
  • tmux: 3.0+
  • Claude Code CLI: 最新版
  • Claude Plan: Pro プラン(使用量上限に注意)

はじめに

Claude Code を使った開発において、「Product Manager」「Architect」「Lead Engineer」「Frontend Engineer」「Backend Engineer」といった複数の役割を同時に運用したいと考えたことはないだろうか。単一セッションでは役割の切り替えが難しく、作業の一貫性を保つのも困難である。

この記事では、tmux を活用して複数の Claude Code セッションを並列起動し、エージェント間通信を可能にする開発システムを紹介する。実際に運用中のシステムをベースに、技術実装から効果まで詳しく解説していく。

システム概要

基本構成

このシステムは以下の要素で構成される。

  1. tmux ペインレイアウト: 複数ペインでエージェントを並列実行
  2. 自動初期化スクリプト: エージェント一括起動・設定
  3. エージェント間通信機能: メッセージ送受信システム
  4. 統制ルール: CLAUDE.md による共通ガイドライン

エージェント役割分担

実際に運用している役割構成は次の通りである。

  • Product Manager: 要件定義・プロジェクト管理
  • Architect: 技術選定・システム設計
  • {Project} Lead: タスク分割・進捗管理
  • {Project} FE: フロントエンド実装
  • {Project} BE: バックエンド実装
  • Blog Writer: 技術記事作成

各エージェントは独立した Claude Code セッションで動作し、専門領域に特化した対話が可能である。

技術実装

tmux ペインレイアウト

# 基本レイアウト作成
tmux split-window -h

# 左ペイン分割(縦4分割)
tmux select-pane -t 0
tmux split-window -v
tmux split-window -v  
tmux split-window -v
tmux resize-pane -t 0 -y 10
tmux resize-pane -t 1 -y 30
tmux resize-pane -t 2 -y 10
tmux resize-pane -t 3 -y 10

# 右ペイン分割(縦3分割)
tmux select-pane -t 4
tmux split-window -v
tmux split-window -v
tmux resize-pane -t 4 -y 20
tmux resize-pane -t 5 -y 20
tmux resize-pane -t 6 -y 20

この構成により、6つの独立したエージェントペインと1つのメインペインを確保している。

自動初期化システム(init.sh

エージェントの一括初期化は以下の流れで実行される。

#!/bin/bash

# 役割定義(ペインインデックス順)
declare -a roles=(
    "Product Manager"
    "Architect" 
    "Blog Writer"
    "${PROJECT_NAME} Lead"
    "${PROJECT_NAME} FE"
    "${PROJECT_NAME} BE"
)

# 初回プロンプトテンプレート
get_initial_prompt() {
    local role=$1
    echo "あなたは ${role} です。ドキュメントからその役割を読み込んで、把握してください。指示があるまで待機してください。"
}

重要なのは、各エージェントに統一された初期化プロンプトを送信することである。これにより、役割認識の一貫性を保っている。

初期化の核心となるのは、tmux のペイン情報を取得する以下のコマンドである。

# ペイン情報を取得する
panes=$(tmux list-panes -F "#{pane_index},#{pane_id}")

このコマンドにより、現在のセッションに存在するすべてのペインの「インデックス」と「ID」を取得できる。この情報が後述のエージェント間通信で重要な役割を果たす。

# 各ペインに対して、エージェントを初期化する
index=0
while IFS= read -r line; do
    pane_index=$(echo $line | cut -d',' -f1)
    pane_id=$(echo $line | cut -d',' -f2 | xargs)

    # ペインインデックス0はスキップ(メインペイン)
    if [ "$pane_index" -eq 0 ]; then
        continue
    fi

    # 対応する役割を取得
    if [ $index -lt ${#roles[@]} ]; then
        role=${roles[$index]}
        echo "📍 ペイン $pane_index ($pane_id): $role を初期化中..."
        
        # 連絡先ファイルに記録
        echo "| $pane_index | $pane_id | $role |" >> agent-contacts.txt

        # claude コマンド実行する
        tmux send-keys -t $pane_id "claude" Enter
        sleep 3

        # 初回プロンプトを送信する
        prompt=$(get_initial_prompt "$role")
        tmux send-keys -t $pane_id "$prompt"
        sleep 1
        tmux send-keys -t $pane_id Enter
        sleep 1

        echo "✅ $role 初期化完了"
        ((index++))
    fi
done <<< "$panes"

このプロセスにより、エージェント連絡先ファイル(agent-contacts.txt)が自動生成され、後述の通信システムで活用される。

生成される agent-contacts.txt の実際の例:

# エージェント連絡先
| Pane Index | Pane ID | Agent Role |
|------------|---------|------------|
| 1 | %2 | Product Manager |
| 2 | %3 | Architect |
| 3 | %4 | Blog Writer |
| 4 | %1 | SampleProject Lead |
| 5 | %5 | SampleProject FE |
| 6 | %6 | SampleProject BE |

このファイルにより、役割名からtmuxペインIDを逆引きしてメッセージ送信が可能になる。

エージェント間通信システム(send-message.sh

エージェント間の連携は専用スクリプトで実現している。

#!/bin/bash

# 使用方法: ./send-message.sh <To Agent Role> <From Agent Name> <Message>

TO_AGENT_ROLE=$1
FROM_NAME=$2  
MESSAGE=$3

# 役割名からペインIDを検索
TO_PANE_ID=$(grep "| $TO_AGENT_ROLE |" agent-contacts.txt | awk -F'|' '{print $3}' | xargs)

if [ -z "$TO_PANE_ID" ]; then
    echo "❌ エージェント '$TO_AGENT_ROLE' が見つかりません。"
    exit 1
fi

# メッセージの先頭に[from:{自分の名前}]を追加
FORMATTED_MESSAGE="[from:${FROM_NAME}] ${MESSAGE}"

# tmuxセッションに送信
tmux send-keys -t ${TO_PANE_ID} "${FORMATTED_MESSAGE}"
sleep 1  
tmux send-keys -t ${TO_PANE_ID} Enter

この仕組みにより、例えば以下のようなエージェント間連携が可能になる。

# Product Manager から Architect へ設計指示
./send-message.sh "Architect" "Product Manager" "要件定義が完了しました。詳細設計を開始してください。"

# Architect から Lead Engineer へタスク分割指示  
./send-message.sh "SampleProject Lead" "Architect" "設計が完了しました。実装タスクの分割をお願いします。"

統制システム(CLAUDE.md 絶対原則)

全エージェントは共通の「絶対原則」に従って動作する。

## 絶対原則

- 日本語で応答すること
- ファイル内容に更新があったら、リモートリポジトリにプッシュすること
- 他のエージェントに連絡するときは `./send-message.sh <To Agent Role> <From Agent Name> <Message>`
- 対話内容が `[from:{Agent Name}]` から始まる場合、他のエージェントからの対話であり、以下に従うこと
  - 作業指示である場合、作業が完了したときに指示者に作業完了報告をする
  - 作業完了報告である場合、次の指示が必要ならば指示を出し、不要ならそれ以上の応答は必要ない
- プロダクトオーナーの応答が必要なときは `windows-notify -t {自分の名前} -m {連絡内容}`
- すべてのチャットの冒頭に、この絶対原則を画面出力してから応答すること

この原則により、エージェント間の一貫した動作とワークフローが保証される。

実際の動作例

エージェント初期化フロー

$ ./init.sh
🚀 エージェント初期化を開始します...
📍 ペイン 1 (%1): Product Manager を初期化中...
✅ Product Manager 初期化完了
📍 ペイン 2 (%2): Architect を初期化中...
✅ Architect 初期化完了
📍 ペイン 3 (%3): Blog Writer を初期化中...
✅ Blog Writer 初期化完了
📍 ペイン 4 (%4): SampleProject Lead を初期化中...
✅ SampleProject Lead 初期化完了
📍 ペイン 5 (%5): SampleProject FE を初期化中...
✅ SampleProject FE 初期化完了
📍 ペイン 6 (%6): SampleProject BE を初期化中...
✅ SampleProject BE 初期化完了
🎉 全エージェントの初期化が完了しました!

エージェント間連携例

実際のプロジェクトでは次のような連携フローが発生する。

  1. Product Manager が要件を requirements/{project}.md に記録
  2. Architect に設計指示を送信
  3. Architect が詳細設計を {project}/docs/ に作成
  4. {Project} Lead にタスク分割を指示
  5. Lead が実装タスクを {project}/CLAUDE.md に記録
  6. FE/BE Engineer に具体的な実装指示を送信

この一連の流れが、エージェント間通信により自動化される。

メッセージ送信の実例

# 設計完了の報告
$ ./send-message.sh "SampleProject Lead" "Architect" "設計書とAPI仕様書が完成しました。実装タスクの分割を開始してください。"

送信先: SampleProject Lead (ペインID: %4)
送信中: %4
内容: [from:Architect] 設計書とAPI仕様書が完成しました。実装タスクの分割を開始してください。
✅ メッセージ送信完了

受信側のエージェントでは、[from:Architect] プレフィックスにより他エージェントからの指示であることを認識し、適切に作業を開始する。

システムの効果

開発効率の向上

従来の単一セッション開発と比較して、以下の改善を実感している。

  1. 役割専門化: 各エージェントが特定領域に集中できる
  2. 並列作業: 設計と実装を同時進行できる
  3. 品質向上: 専門エージェントによるレビューで品質が向上
  4. 知識継承: 各エージェントが蓄積した文脈を保持する

実際の成果

このシステムを活用した実際のプロジェクトでは、以下の成果を得た。

  • バックエンド: クラウドサービス + NoSQL による完全なAPI実装
  • フロントエンド: モダンフレームワーク + TypeScript による基盤UI(80%完成)
  • プロジェクト管理: 要件定義から実装まで一貫した管理

従来であれば数週間かかる作業を、数日で完成させることができた。

運用上の課題と改善点

現在の課題

  1. メモリ制限: Claude の文脈記憶限界による情報ロスト
  2. セッション管理: 長時間運用時の接続切れ対応
  3. コスト: 複数セッション並列実行によるAPI使用料増加
  4. システムリソース: 低スペックPCでは6エージェント以上で不安定化
  5. 使用量上限: Claude Pro プランでも頻繁に使用量上限に達する

実際の運用制約

  • エージェント数: 当初10名で設計したが、PCスペックの関係で6名に削減
  • 安定性: 6名構成でもたまにシステムが落ちることがある
  • 使用量管理: Pro プランでも長時間の並列運用で上限到達が頻発

改善案

  1. 文脈保存機能: 重要な決定事項の自動保存
  2. セッション復旧: 切断時の自動復旧機能
  3. 選択的起動: 必要なエージェントのみ起動する仕組み
  4. リソース監視: CPU・メモリ使用量の監視機能
  5. 使用量制御: エージェント数の動的調整機能

まとめ

tmux と Claude Code を組み合わせたマルチエージェントシステムにより、従来不可能だった並列開発と役割専門化を実現した。特に以下の点で優れている。

  1. 技術的実現性: 既存ツールの組み合わせで構築可能
  2. 拡張性: 新しい役割を容易に追加できる
  3. 実用性: 実際のプロジェクトで効果を実証済み

このシステムは、個人開発からチーム開発まで、幅広い場面で活用できる。Claude Code を使った開発において、新しい可能性を提示するアプローチとして、ぜひ試してみてほしい。


おわりに

このマルチエージェントシステムは理想的な開発環境を提供する一方で、実用的な制約も多い。特に低スペックPCでの運用やClaude Pro プランの使用量制限は、システム設計時に十分考慮する必要がある。

それでも、適切に運用すれば従来の開発手法では不可能だった並列開発と専門化を実現できる。個人開発者にとって新しい可能性を切り開くアプローチとして、ぜひ検討してほしい。

2025-07-04

Google Blogger API で技術記事投稿を自動化してみた

Google Blogger API で技術記事投稿を自動化してみた

技術ブログの執筆と投稿は、継続的な情報発信において重要な活動である。しかし、記事作成から投稿までの手作業は時間がかかり、効率化の余地がある。

本記事では、Markdown で記事を作成し、Google Blogger API を通じて自動投稿するスクリプトの作成方法を詳しく解説する。OAuth2 認証と環境変数管理に焦点を当てた実践的な実装例を紹介する。

システム要件

前提条件

  • Node.js 16 以上
  • Google アカウント
  • Blogger ブログ

目標とする機能

  • Markdown による記事作成
  • OAuth2 による安全な認証
  • 環境変数による設定管理
  • Google Blogger への自動投稿

アーキテクチャ設計

ディレクトリ構成

├── articles/
│   ├── drafts/          # 作成中の記事
│   ├── review/          # レビュー中の記事
│   ├── published/       # 投稿済みの記事
│   └── templates/       # 記事テンプレート
├── scripts/
│   ├── auth.js          # OAuth2 認証
│   ├── new-article.js   # 記事作成
│   ├── build.js         # HTML ビルド
│   ├── publish-draft.js # Blogger 投稿
│   └── update-article.js # 記事更新
└── blogger-config.json  # API 設定ファイル

技術スタック

  • 言語: JavaScript (Node.js)
  • 認証: Google OAuth2
  • ビルド: Markdown-it + MathJax + Prism.js
  • 設定管理: 環境変数 + JSON

Google Cloud Console の設定

1. プロジェクトの作成と API 有効化

# Google Cloud Console での手順:
# 1. 新しいプロジェクトを作成
# 2. Blogger API を有効化
# 3. OAuth 2.0 認証情報を作成(デスクトップアプリケーション)

2. OAuth2 認証情報の取得

重要な設定項目:

  • アプリケーションの種類: デスクトップアプリケーション
  • リダイレクトURI: urn:ietf:wg:oauth:2.0:oob
  • スコープ: https://www.googleapis.com/auth/blogger

認証システムの実装

OAuth2 認証スクリプト

// scripts/auth.js の主要部分
const { google } = require('googleapis');

async function authenticateUser(config) {
    const { clientId, clientSecret, redirectUri } = config.blogger;
    
    const oAuth2Client = new google.auth.OAuth2(
        clientId,
        clientSecret,
        redirectUri
    );
    
    // 認証URLを生成
    const authUrl = oAuth2Client.generateAuthUrl({
        access_type: 'offline',
        scope: [
            'https://www.googleapis.com/auth/blogger',
            'https://www.googleapis.com/auth/blogger.readonly'
        ]
    });
    
    console.log('認証URL:', authUrl);
    
    // 認証コードを取得(ユーザー入力)
    const authCode = await getUserInput();
    
    // トークンを取得・保存
    const { tokens } = await oAuth2Client.getToken(authCode);
    await fs.writeJson('blogger-token.json', tokens);
    
    return oAuth2Client;
}

環境変数管理

// blogger-config.json
{
  "blogger": {
    "blogId": "${BLOGGER_BLOG_ID}",
    "clientId": "${BLOGGER_CLIENT_ID}",
    "clientSecret": "${BLOGGER_CLIENT_SECRET}",
    "redirectUri": "urn:ietf:wg:oauth:2.0:oob"
  }
}
// 環境変数展開機能
function expandEnvironmentVariables(obj) {
    if (typeof obj === 'string') {
        return obj.replace(/\$\{([^}]+)\}/g, (match, envVar) => {
            return process.env[envVar] || match;
        });
    }
    // 再帰的に処理...
}

記事管理システム

記事作成スクリプト

// scripts/new-article.js の核心部分
function generateFileName(title, date) {
    const dateStr = moment(date).format('YYYYMMDD');
    const titleSlug = title
        .toLowerCase()
        .replace(/[^a-z0-9ひらがなカタカナ漢字]/g, '_')
        .replace(/_+/g, '_')
        .replace(/^_|_$/g, '');
    
    return `${dateStr}_${titleSlug}.md`;
}

function generateArticleContent(options) {
    return `---
title: "${options.title}"
date: "${options.date}"
tags: [${options.tags.map(tag => `"${tag}"`).join(', ')}]
description: "${options.description}"
---

# ${options.title}

## 概要

${options.description}

## 内容

### セクション1

内容を書く
`;
}

ビルドシステム

// scripts/build.js - Markdown から HTML への変換
const MarkdownIt = require('markdown-it');
const markdownItKatex = require('markdown-it-katex');
const Prism = require('prismjs');

const md = new MarkdownIt({
    html: true,
    breaks: true,
    linkify: true,
    highlight: function (str, lang) {
        if (lang && Prism.languages[lang]) {
            return Prism.highlight(str, Prism.languages[lang], lang);
        }
        return '';
    }
});

md.use(markdownItKatex); // 数式対応

Blogger API 連携

記事投稿機能

// scripts/publish-draft.js の主要部分
async function publishToBlogger(auth, blogId, title, content, labels = []) {
    const blogger = google.blogger({ version: 'v3', auth });
    
    const post = {
        kind: 'blogger#post',
        title: title,
        content: content,
        labels: labels
    };
    
    const response = await blogger.posts.insert({
        blogId: blogId,
        resource: post,
        isDraft: true  // 安全のため下書きとして投稿
    });
    
    return response.data;
}

エラーハンドリング

// 認証エラーの詳細処理
catch (error) {
    if (error.message.includes('access_denied')) {
        console.log('OAuth 同意画面でテストユーザーを追加してください');
    } else if (error.message.includes('invalid_client')) {
        console.log('クライアントIDとシークレットを確認してください');
    }
}

セキュリティ考慮事項

機密情報の管理

# .gitignore に追加すべき項目
blogger-token.json
*.local.json
.env
.env.local

環境変数の設定

# 本番環境での設定例
export BLOGGER_CLIENT_ID="your-client-id"
export BLOGGER_CLIENT_SECRET="your-client-secret"
export BLOGGER_BLOG_ID="your-blog-id"

使用方法

基本的な使い方

# 1. 認証設定(初回のみ)
node scripts/auth.js

# 2. 記事をMarkdownで作成(手動)
# articles/drafts/your-article.md

# 3. HTML にビルド
node scripts/build.js your-article.md

# 4. Blogger に下書きとして投稿
node scripts/publish-draft.js your-article.md

# 5. 既存記事の更新
node scripts/update-article.js your-article.md

便利なコマンド

# 記事一覧の表示
node scripts/publish-draft.js --list

# ヘルプ表示
node scripts/publish-draft.js --help

トラブルシューティング

OAuth 認証エラー

問題: "アクセスをブロック: 認証エラーである"
解決: Google Cloud Console でテストユーザーを追加

性能と拡張性

最適化のポイント

  1. キャッシュ活用: 認証トークンの適切な管理
  2. 並列処理: 複数記事の一括処理対応
  3. エラー回復: リトライ機能の実装
  4. ログ管理: 詳細なログ出力

今後の拡張案

  • 画像の自動アップロード機能
  • SEO メタデータの自動生成
  • SNS への自動投稿連携
  • 記事のスケジュール投稿機能

まとめ

本記事では、Google Blogger API を活用した技術記事の自動投稿方法を解説した。

実現できたこと

  • 効率的な記事管理: Markdown による記事作成
  • 安全な認証: OAuth2 による API 連携
  • シンプルな構成: 複雑な依存関係のない軽量システム
  • 自動投稿: Google Blogger への直接投稿

学んだポイント

  1. OAuth2 認証の実装: Google API との安全な連携方法
  2. 環境変数管理: セキュリティを考慮した設定管理
  3. Node.js スクリプト: 実用的な CLI ツールの作成
  4. システム設計: 複雑性を排除したシンプルなアーキテクチャ

このスクリプトにより、技術記事の執筆から投稿までの作業を大幅に効率化できた。Google Blogger API は思った以上に使いやすく、個人ブログの自動化には最適である。

参考文献


執筆について: この記事は Claude Code (claude.ai/code) との協働により執筆され、実際に構築した自動投稿スクリプトを使用して Blogger に投稿されている。

ラビット・チャレンジ - Stage 3. 深層学習 前編 (Day 1)

提出したレポートです。 絶対書きすぎですが、行間を埋めたくなるので仕方ない。 Rabbit Challenge - Stage 3. 深層学習 前編 (Day 1) 0. 深層学習とは何か この講義(Day1)の内容では、ニューラルネットワークを用いた学習方法として、順...