Mac での Computer Use 実装
2026年3月24日、Anthropic は Claude の Computer Use 機能を macOS に正式対応させました。これは単なる機能追加ではなく、デスクトップ自動化のパラダイムシフトです。従来のスクリプト言語やRPA ツールの課題——セッション管理の複雑さ、エラーハンドリングの脆弱性、メンテナンスコストの高さ——を Claude の自然言語処理と推論能力で解決できるようになりました。
実装パターン 1: 夜間バッチ処理(Overnight Batch Processing)
シナリオ
営業チームが日々エクスポートする Excel レポート(売上、顧客獲得、チャーン率)を、毎晩 22:00 に自動で集計し、Google Sheets にアップロードします。ローカルの Excel ファイルを検出→変換→クラウド同期。
パターンの核:セキュリティフィースト
【重要】バッチ処理前のセキュリティチェック
1. ファイルの在り処確認($HOME/Downloads など指定ディレクトリのみ)
2. ファイル署名の検証(既知のレポート形式か)
3. 操作の事前ドライラン(実際に変更を行う前に概要出力)
4. ログ記録(スクリーンショット・操作履歴を /var/log/batch_automation にて保存)
5. 失敗時の自動ロールバック+管理者への Slack 通知
実装例:Python + Dispatch
# batch_processor.py - 毎晩22:00に実行
import os
import json
from datetime import datetime
from pathlib import Path
import subprocess
MONITORED_DIR = Path.home() / "Downloads" / "reports"
ALLOWED_PATTERNS = ["sales_*.xlsx", "churn_*.xlsx", "acq_*.xlsx"]
LOG_FILE = Path("/var/log/batch_automation") / f"{datetime.now():%Y%m%d}.log"
def validate_file(file_path: Path) -> bool:
"""ファイルが許可されたパターンに合致するか確認"""
return any(
file_path.name == pattern.replace("*", file_path.stem.split("_")[-1])
for pattern in ALLOWED_PATTERNS
)
def log_operation(operation: str, status: str, details: dict) -> None:
"""操作ログを記録"""
log_entry = {
"timestamp": datetime.now().isoformat(),
"operation": operation,
"status": status,
"details": details
}
with open(LOG_FILE, "a") as f:
f.write(json.dumps(log_entry) + "\n")
def main():
# ステップ1: ファイル検出
files_to_process = [
f for f in MONITORED_DIR.glob("*.xlsx")
if validate_file(f)
]
if not files_to_process:
log_operation("file_detection", "no_files", {})
return
# ステップ2: ドライラン(実際に変更を行わない)
print(f"[DRY RUN] 処理対象ファイル: {len(files_to_process)} 件")
for file in files_to_process:
print(f" - {file.name} ({file.stat().st_size / 1024:.1f} KB)")
# ステップ3: 確認画面表示(Computer Use エージェントが人間の確認を待つ)
input("\n本処理を実行してもよろしいですか? (Enterで続行, Ctrl+Cでキャンセル): ")
# ステップ4: 本処理
for file in files_to_process:
try:
# Excel を CSV に変換
output_file = file.with_suffix(".csv")
subprocess.run([
"ssconvert",
str(file),
str(output_file)
], check=True, capture_output=True)
# Google Sheets にアップロード(別途スクリプト)
subprocess.run([
"python", "upload_to_sheets.py",
"--file", str(output_file),
"--sheet-id", os.environ["GOOGLE_SHEET_ID"]
], check=True)
log_operation("process_file", "success", {"file": file.name})
except Exception as e:
log_operation("process_file", "failed", {
"file": file.name,
"error": str(e)
})
# 管理者に通知
subprocess.run([
"curl", "-X", "POST", os.environ["SLACK_WEBHOOK"],
"-H", "Content-Type: application/json",
"-d", json.dumps({
"text": f"❌ バッチ処理エラー: {file.name} - {str(e)}"
})
])
if __name__ == "__main__":
main()実行方法:
macOS の cron または launchd で毎日 22:00 に実行。ただし Computer Use を使う場合は、Dispatch フレームワークの @scheduled デコレータを使用:
from anthropic_dispatch import scheduled
@scheduled("0 22 * * *") # 毎日 22:00
async def nightly_batch_automation():
"""Claude Computer Use に バッチ処理を依頼"""
# Dispatch がバックグラウンドで自動実行実装パターン 2: マルチアプリケーション連携(Multi-App Orchestration)
シナリオ
営業会議前に、以下の一連の操作を自動実行:
- Slack から今週の新規案件情報を取得
- Notion のCRM データベースに顧客情報を記録
- Figma から最新のプレゼン資料をダウンロード
- Keynote で資料を開き、数字を最新のものに更新
- Google Meet のリンクを Slack に投稿
パターンのポイント:アプリケーション間の「状態同期」
各アプリの操作は独立している可能性があります。ウィンドウの切り替え、フォーカス喪失、ダイアログの予期しない表示など、実世界の雑音に対応する必要があります。
【重要】マルチアプリ自動化の堅牢性
1. 各ステップの前後に スクリーンショット を自動キャプチャ
2. OCR で画面上の要素を認識(座標ベースでなく内容ベース)
3. 失敗検出:アプリが応答しない、エラーダイアログ表示など
4. フォールバック戦略:うまくいかなかった場合の代替手段
5. ステップ間の待機時間を柔軟に調整(ネットワーク遅延対応)
実装例
# multi_app_orchestration.py
import anthropic
from anthropic_dispatch import dispatch
import time
client = anthropic.Anthropic()
async def orchestrate_meeting_prep():
"""会議準備のマルチアプリ連携"""
steps = [
{
"app": "Slack",
"action": "チャンネル #sales_leads から過去24時間のメッセージを読む",
"timeout": 30
},
{
"app": "Notion",
"action": "新規案件情報を CRM データベースに追加",
"timeout": 60
},
{
"app": "Figma",
"action": "最新の'Weekly_Metrics' デザインをダウンロード",
"timeout": 45
},
{
"app": "Keynote",
"action": "ダウンロードしたデザインを開き、昨日の売上数字を更新",
"timeout": 90
},
{
"app": "Google Meet",
"action": "会議リンク作成、Slack #sales_team に投稿",
"timeout": 45
}
]
results = []
for i, step in enumerate(steps, 1):
try:
print(f"\n[{i}/{len(steps)}] {step['app']}: {step['action']}")
# Computer Use で実行
response = await client.messages.create(
model="claude-opus-4-6",
max_tokens=2048,
tools=[
{
"type": "computer_use",
"name": "computer_use"
}
],
messages=[{
"role": "user",
"content": step['action']
}]
)
# スクリーンショット取得(確認用)
screenshot = client.beta.messages.create(
model="claude-opus-4-6",
max_tokens=1024,
messages=[{
"role": "user",
"content": "スクリーンショットを取り、現在の状態を説明してください"
}]
)
results.append({
"step": step['app'],
"status": "success",
"response": response.content[0].text if response.content else ""
})
# ステップ間の待機
time.sleep(3)
except Exception as e:
results.append({
"step": step['app'],
"status": "failed",
"error": str(e)
})
# エラー時は次ステップをスキップするか判断
if "critical" in str(e).lower():
break
return results実装パターン 3: スプレッドシート自動化
シナリオ
Google Sheets の営業パイプラインを自動更新。データの入力→計算→フォーマット→グラフ作成を自動化。
ポイント
【重要】スプレッドシート自動化の注意点
1. API キー、シートID などの認証情報を環境変数に保管(コードに埋め込まない)
2. 大量編集時は バッチ処理 API を使用(行ごとの個別編集を避ける)
3. 計算式の循環参照チェック
4. 条件付き書式の自動適用(売上目標未達の行を赤くするなど)
5. スクリーンショット確認後に最終確定(誤ったフォーマットを防ぐ)
# spreadsheet_automation.py
import gspread
from anthropic_dispatch import dispatch
import os
# Google Sheets API 初期化
gc = gspread.service_account(
filename=os.environ["GOOGLE_SERVICE_ACCOUNT_JSON"]
)
def update_sales_pipeline():
"""営業パイプラインの自動更新"""
# スプレッドシート取得
sh = gc.open_by_key(os.environ["PIPELINE_SHEET_ID"])
ws = sh.worksheet("Pipeline")
# 現在のデータを読む
all_records = ws.get_all_records()
# 戦略1:新しい案件を自動ランク付け(POT = Probability of Closure × Deal Size)
for i, record in enumerate(all_records, 2): # ヘッダーをスキップ
prob = float(record.get("Close_Probability", 0))
deal_size = float(record.get("Deal_Size", 0))
pot = prob * deal_size
ws.update_cell(i, ws.find("POT").col, f"{pot:,.0f}")
# 戦略2:月末まであと何日かを計算
from datetime import datetime, date
today = date.today()
days_left = (
date(today.year, today.month + 1, 1) - today
).days if today.month < 12 else (
date(today.year + 1, 1, 1) - today
).days
# 期限が近い案件に警告を付ける(条件付き書式)
ws.format("B:B", {
"conditionalFormats": [
{
"ranges": ["B2:B100"],
"booleanRule": {
"condition": {
"type": "CUSTOM_FORMULA",
"values": [f"=DAYS($B$2,TODAY()) < {days_left}"]
},
"format": {
"backgroundColor": {"red": 1, "green": 0.8, "blue": 0.8}
}
}
}
]
})
print("✅ パイプライン更新完了")実装パターン 4: ブラウザオートメーション
シナリオ
競合他社の価格監視。複数の E コマースサイト、SaaS プラン、広告主の価格ページを定期的にスクレイピングし、Price List Google Sheet に自動更新。
セキュリティと法的考慮
【重要】ブラウザオートメーションの合法性・倫理性
1. robots.txt を確認:スクレイピング対象サイトが許可しているか
2. 利用規約の確認:データ取得の禁止条項がないか
3. API の優先利用:公開 API があればそちらを利用
4. リクエスト間隔の設定:サーバー負荷を避けるため最低1秒の間隔
5. User-Agent の設定:正直に "Claude Computer Use Automation / 1.0" と名乗る
6. キャッシュの活用:同一ページの再訪問を避ける
# price_monitoring.py
import asyncio
import random
from datetime import datetime
import gspread
from anthropic_dispatch import dispatch
PRICE_MONITORING_TASKS = [
{
"name": "competitor_A_pricing",
"url": "https://competitor-a.com/pricing",
"selectors": {
"basic_plan": ".pricing__tier:nth-child(1) .price",
"pro_plan": ".pricing__tier:nth-child(2) .price"
}
},
{
"name": "competitor_B_pricing",
"url": "https://competitor-b.com/plans",
"selectors": {
"starter": "#plan-starter .amount",
"professional": "#plan-pro .amount"
}
}
]
async def monitor_competitor_prices():
"""競合他社の価格を監視・記録"""
gc = gspread.service_account()
sh = gc.open("Price_Monitoring")
ws = sh.worksheet(datetime.now().strftime("%Y-%m"))
for task in PRICE_MONITORING_TASKS:
try:
# 間隔を設定(サーバー保護)
await asyncio.sleep(random.uniform(2, 5))
# Computer Use で価格ページを訪問
# (JavaScript実行が必要な場合)
from anthropic_dispatch import dispatch
result = await dispatch(
model="claude-opus-4-6",
prompt=f"""
以下のURLにアクセスして、価格情報を取得してください:
{task['url']}
以下の要素から価格を抽出:
{json.dumps(task['selectors'])}
JSONフォーマットで結果を返してください
"""
)
# Google Sheets に記録
row = [
datetime.now().isoformat(),
task['name'],
json.dumps(json.loads(result))
]
ws.append_row(row)
except Exception as e:
print(f"❌ {task['name']} 失敗: {e}")実装パターン 5: Xcode ビルド自動化
シナリオ
複数のiOS アプリのCI/CD パイプライン。毎日深夜にテストビルドを実行し、結果をSlack に通知。
パターン:エラー検出と復旧
【重要】ビルドオートメーションの堅牢性
1. ビルド前チェック:CocoaPods 更新、署名証明書の有効性
2. エラーログのリアルタイム監視:構文エラー、リンクエラーなど
3. 自動クリーンアップ:Derived Data のクリア(容量確保)
4. 失敗時の自動レポート:ログの Slack 投稿、重要開発者への通知
5. ロールバック戦略:ビルド失敗時は前回成功したコミットに戻す
# xcode_automation.py
import subprocess
import json
import os
from datetime import datetime
PROJECTS = [
{"path": "/Users/dev/Projects/App_A", "scheme": "App_A"},
{"path": "/Users/dev/Projects/App_B", "scheme": "App_B"}
]
def build_ios_app(project_path: str, scheme: str) -> dict:
"""iOS アプリをビルド"""
try:
# ステップ1:ビルド環境確認
print(f"🔍 {scheme} のビルド環境を確認中...")
# ステップ2:CocoaPods 更新
subprocess.run(
["pod", "repo", "update"],
cwd=project_path,
check=True,
capture_output=True
)
# ステップ3:ビルド実行
print(f"🏗️ {scheme} をビルド中...")
result = subprocess.run(
[
"xcodebuild",
"-scheme", scheme,
"-configuration", "Debug",
"-derivedDataPath", "/tmp/xcode_build",
"build"
],
cwd=project_path,
capture_output=True,
text=True
)
if result.returncode == 0:
return {
"status": "success",
"scheme": scheme,
"timestamp": datetime.now().isoformat(),
"message": "✅ ビルド成功"
}
else:
# エラーログを解析
error_lines = [
line for line in result.stderr.split('\n')
if "error:" in line.lower()
]
return {
"status": "failed",
"scheme": scheme,
"timestamp": datetime.now().isoformat(),
"errors": error_lines[:5], # 最初の5エラーのみ
"message": "❌ ビルド失敗"
}
except Exception as e:
return {
"status": "failed",
"scheme": scheme,
"error": str(e),
"message": "❌ 例外エラー"
}
def notify_slack(results: list) -> None:
"""Slack に通知"""
webhook_url = os.environ["SLACK_WEBHOOK_URL"]
# 結果をサマリー
success_count = sum(1 for r in results if r["status"] == "success")
failed_count = len(results) - success_count
message = {
"text": f"🔨 Daily iOS Build Report: {success_count}/{len(results)} 成功",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*Daily iOS Build*\n成功: {success_count}, 失敗: {failed_count}"
}
}
]
}
# 失敗したビルドの詳細を追加
for result in results:
if result["status"] == "failed":
message["blocks"].append({
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*❌ {result['scheme']}*\n```{json.dumps(result['errors'], indent=2)}```"
}
})
# Slack に POST
subprocess.run([
"curl", "-X", "POST", webhook_url,
"-H", "Content-Type: application/json",
"-d", json.dumps(message)
])
def main():
results = []
for project in PROJECTS:
result = build_ios_app(project["path"], project["scheme"])
results.append(result)
print(f" → {result['message']}")
# Slack 通知
notify_slack(results)
if __name__ == "__main__":
main()セキュリティベストプラクティス
1. 認証情報の管理
# ❌ 禁止:コードに直接埋め込む
API_KEY = "sk-xxx..."
# ✅ 推奨:環境変数から読み込む
API_KEY = os.environ["SLACK_API_KEY"]
# さらに安全:macOS Keychain から取得
import subprocess
api_key = subprocess.run(
["security", "find-generic-password", "-w", "-s", "slack_api"],
capture_output=True, text=True
).stdout.strip()2. 操作の監査ログ
すべての自動化操作を記録。
{
"timestamp": "2026-03-25T22:00:15Z",
"operation": "batch_report_sync",
"user_initiated": false,
"files_processed": 12,
"success": true,
"duration_seconds": 145,
"screenshot_before": "/var/log/automation/20260325_220000_before.png",
"screenshot_after": "/var/log/automation/20260325_220145_after.png"
}3. 権限の最小化
Computer Use のアクセス範囲を制限。
許可するディレクトリ:
- $HOME/Documents/Reports
- $HOME/Downloads/Incoming
禁止するディレクトリ:
- $HOME/.ssh
- $HOME/Library/Keychains
- /private/var/db
結論
Claude Computer Use × Dispatch の組み合わせは、デスクトップ自動化の大きな飛躍です。プロダクション環境での運用には、セキュリティ・可観測性・エラーハンドリングの 3 点が不可欠です。本ガイドで紹介したパターンを参考に、貴社の業務に合わせたカスタマイズを行ってください。
次のステップとしては、Claude Code Hooks 自動化ガイドで、より細粒度の GitHub Actions 連携について学んだり、Claude Dispatch 完全ガイドで、リモートワーカー向けの最適なセットアップをご確認ください。