「Claude Code」タグアーカイブ

Obsidian頭脳化計画:AIエージェントの外部記憶をObsidian Vaultで実現する

はじめに

最近はやりのObsidianで外部脳を作ろうというkarpathyさんのアイデアをちょっと違う形でAI Agent向けの外部脳を作ってみました。私は、ClaudeCodeがメインでOpenCalw、kiro、Antigravity、OpenCladeなど。。。節操なく使ておりり、各エージェント事にコンテキストがバラバラという課題がありまして、これをNAS+Obsidianで効率的に共有できないかと考えました。 私はRedmineでプロジェクト管理しているので、Redmineをベースに、Obsidian Vaultを全AIエージェント共通の外部記憶として整備するプロジェクト「redobrain」を始めました。

何を作ったのか

一言で言うと、Redmineに書いた情報を自動的にObsidian Vaultに取り込み、AIが読みやすい形に統合するパイプラインです。基本的にはOpenClawのSKILLSで、スクリプトを実行させたりマージはLLMにやらせてます。この仕組み自体、私がアイデアを出しClaudeCodeで作成したものです。

人間 → Redmineにチケットを書く
         ↓ (自動同期)
    Sources/Redmine/ に1チケット1ファイルで保存
         ↓ (ルールベース分類)
    classify-state.json に分類結果を記録
         ↓ (OpenClawが直接マージ)
    Merged/ に統合ドキュメントとして出力
         ↑
    他のAI Agentが ENTRY.md 経由で参照

人間がやることは「Redmineにチケットを書く」だけ。あとは全自動です。

設計原則:Sourcesが唯一の真実

このシステムの核となる設計原則は:

Sources が唯一の真実。Merged はビルド成果物。

プログラマーなら馴染みのある考え方ですね。ソースコードとビルド成果物の関係と同じです。

  • Sources/ = ソースコード(Redmineチケット、手動投入ドキュメント)
  • Merged/ = ビルド成果物(AIが読む統合ドキュメント)
  • いつでも Sources/ から Merged/ を再生成できる

これにより「マージ済みだからスキップ」という判断が不要になります。ルールが変わった、情報が更新された → 再生成すればいい。シンプルです。

2フェーズ・アーキテクチャ

Phase 1: Classify(ルールベース、LLM不要)

分類はLLMを使いません。純粋なルールベースです。

  • Redmineチケットの parent_id を辿ってルートチケットを特定
  • ルートチケット = コアドキュメント(統合先)
  • 子チケットは親のコアドキュメントに分類される
def _find_root(self, ticket_id, parent_map):
    """parent_idチェーンを辿ってルートを見つける(循環検出付き)"""
    visited = set()
    current = ticket_id
    while current in parent_map and parent_map[current] is not None:
        if current in visited:
            break
        visited.add(current)
        current = parent_map[current]
    return current

最初は分類もOpenClawにやらせようと思ったのですが、いまいちだったのでRedmineのプロジェクトをベースにClaudeCodeで先に仕分けルールを作らせました。

Phase 2: Merge(OpenClawが直接実行)

SKILLS.mdでスクリプト実行とその結果で判断させ、マージの仕方を指示しています。

## マージ作業(あなたが直接行う — スクリプト不要)

**重要**: マージは2フェーズに分けて行う。1回の処理を小さく保つこと。

### 「マージして」と言われたら即座にこれを実行する

**⚠️ 絶対に聞き返さない。追加情報を求めない。以下をそのまま実行する。**

何をマージするか、どこにマージするかは聞かなくてよい。classify コマンドが自動判定する。

```bash
# Step 1: 分類(自動)— 何をマージすべきか自動判定される
cd ~/.openclaw/workspace/skills/redobrain
set -a; source systemd/openclaw.env; set +a
python3 -m scripts.main --config /mnt/share/Obsidian/_openclaw/config.yaml classify
```

```bash
# Step 2: 次のマージ対象を確認 — これが「何をマージするか」の答え
python3 -m scripts.main --config /mnt/share/Obsidian/_openclaw/config.yaml next-merge
```

**Step 2 の出力を見て、そこに書かれた core_doc と sources に従って作業する。**
ユーザーに何も聞く必要はない。

Step 3以降はあなたが直接ファイルを読み書きして行う:

**⚠️ 1回のセッションで処理するのは1コアドキュメントのみ。**

```
Step 3: next-merge の出力を確認 → core_doc と sources 一覧を把握する
Step 4: その core_doc に属する Sources を1件ずつ読む(一度に全部読まない)
Step 5: 内容を理解し、コアドキュメントを作成・更新する
         - 既存ファイルがあれば先に Archive に退避
           cp /mnt/share/Obsidian/Merged/xxx.md /mnt/share/Obsidian/Archive/Merged/xxx_YYYY-MM-DD_HHmm.md
         - /mnt/share/Obsidian/Merged/{category}/{name}.md に書き込む
Step 6: マージ完了したら mark-merged で記録する
         python3 -m scripts.main --config /mnt/share/Obsidian/_openclaw/config.yaml mark-merged "Merged/xxx/yyy.md"
Step 7: Discord に完了を報告する(例:「Merged/Trading/daytrade-bot.md をマージしました」)
Step 8: /mnt/share/Obsidian/00-Entry/ENTRY.md を更新する
         - 統合ドキュメント一覧のパスは Obsidian wiki-link で記載する
         - 例: `[[Merged/Trading/daytrade-bot]]` (.md は省略)
         - テーブル形式: `| タイトル | [[Merged/Trading/daytrade-bot]] | 概要 | 日付 |`
Step 9: /mnt/share/Obsidian/_openclaw/logs/YYYY-MM-DD.md にログを記録する
```

Vault構造

/mnt/share/Obsidian/
├── 00-Entry/
│   └── ENTRY.md              ← 全AIエージェントの入口
├── Sources/
│   ├── Redmine/              ← チケットごとに1ファイル
│   └── Other/                ← 手動投入ドキュメント
├── Merged/                   ← 統合ドキュメント(カテゴリ別)
│   ├── Trading/
│   ├── Projects/
│   ├── Infrastructure/
│   └── ...
├── Archive/
│   └── Merged/               ← 過去バージョン(自動退避)
└── _openclaw/
    ├── config.yaml
    ├── merge_rules.yaml      ← 分類ルール定義
    ├── classify-state.json   ← 分類結果キャッシュ
    └── logs/

ポイントは 00-Entry/ENTRY.md の存在です。どのAIエージェントも、このファイルを1つ読めば全情報にアクセスできる。設定ファイルに1行追加するだけ:

プロジェクト情報は /mnt/share/Obsidian/00-Entry/ENTRY.md を参照。

実装の工夫

増分処理

毎回全チケットを再分類するのは無駄なので、classified_atlast_synced を比較して変更があったものだけ処理します。

# 増分処理: 前回分類済みで変更なしならスキップ
existing = sources.get(source_path)
if existing and existing.get("classified_at", "") >= last_synced:
    continue

アーカイブ自動退避

マージ前に既存の Merged/ ファイルがあれば、自動的に Archive/ にタイムスタンプ付きでコピーします。git的な発想ですが、Obsidianのプレーンマークダウンという制約の中では十分実用的です。

ロックファイル

NAS上のVaultに複数プロセスが同時アクセスしないよう、シンプルなロックファイル機構を実装しています。タイムアウト付きで、デッドロックも防止。

技術スタック

  • Python 3.11+ — パイプラインスクリプト
  • OpenClaw — LLMエージェント基盤(Qwen3.6-35b-a3b on Ollama)
  • Redmine — 情報の入力元(人間が書く場所)
  • Obsidian — 情報の出力先(AIが読む場所)
  • Discord — 承認フロー・通知
  • NAS (SMB/NFS) — Vault の物理ストレージ(複数マシンからアクセス可能)

技術スタック

利用環境

  • Windows 11 (Claude Code/kiro/Antigravity) 普段使うPC
  • Ubuntu Linux 24.04(Openclaw/Claude Code/kiro-cli) Openclawマシン
  • Mac mini(まだ届いてない(笑))

現在の稼働状況

  • Redmine sync: 稼働中(329チケット同期済み)
  • Classify: 稼働中(273ソース分類済み → 157コアドキュメント)
  • Merge: OpenClawによる実行が進行中
  • systemdタイマーで15分ごとに自動実行

なぜObsidianなのか

「なぜNotionやConfluenceではなくObsidianか?」という疑問があるかもしれません。理由は明確です:

  1. プレーンマークダウン — APIもDBも不要。ファイルを読むだけ
  2. ローカルファイルシステム — AIエージェントが直接アクセスできる
  3. NASマウント — 複数マシン(Windows/Linux/Mac)から同じVaultにアクセス
  4. Obsidianのwiki-link — ドキュメント間のリンクが簡潔に書ける
  5. 人間も読める — Obsidianアプリで普通にブラウズ・編集できる

AIエージェントにとって最も低摩擦なインターフェースは「ファイルを読む」こと。それ以上でもそれ以下でもない。

今後の展望

  • マージ品質の改善(現在はOpenClawの出力をそのまま使っているが、フォーマットの一貫性にばらつきがある)
  • 定期的な全再マージ(ルール変更時に一括再生成)
  • 他のAIエージェント(Claude Code、Kiro等)からの参照実績を積む
  • Sources/Other/ への手動投入ワークフローの整備

まとめ

redobrainは「AIエージェントに長期記憶を持たせる」という課題に対する、実用的な解答です。

設計のポイントは:

  • 人間はRedmineに書くだけ(既存ワークフローを変えない)
  • 分類はルールベース(LLMの気まぐれに依存しない)
  • 統合はLLMが直接実行(エージェントの強みを活かす)
  • 出力はプレーンマークダウン(どのAIからも読める)

ぶっちゃけ、これClaude Codeに課金してやらせたら簡単に終わると思います。それをケチって(いや、実験として)OpenClaw + Ollamaで実行させるためには、JOBを細かく切るとかちょっとお馬鹿でも実行できるようにするとか一部、スクリプトを作るとかってことをしてる訳ですね。まぁ、不毛っちゃ不毛です(笑)

環境: OpenClaw v2026.5.4 / Ollama 0.20.5 / Qwen3.6-35b-a3b / RTX 3060 12GB / Ryzen 5600X / RAM 32GB / Obsidian on NAS (SMB)

OpenClaw+ClaudeCodeで補完する

概要

OpenClawはClaudeCodeに比べるとまだまだ不安定で色々いじるとすぐ動かなくなる。それにローカルLLMを使っているのでClaudeほど賢くない。そこで、Claude CodeにOpenClawの管理者・先生となってもらって、OpenClawを育てれ見ようと思った。

相互補完の関係

  • ClaudeCodeBot-a10 1 → OpenClawの不安定な状態のメンテナンスや指示出しを担当
  • OpenClaw → ClaudeCodeBot-a10の再起動や状態監視を担当

実現した機能

  1. Discordを通じた人間とのコミュニケーション: Discordチャンネルから直接操作
  2. Remote Control機能を使ったオペレーション: iPhoneアプリからリモート操作
  3. 常駐化による安定運用: コンテキスト維持と即時応答

この構成により、AIアシスタント同士の協調作業と、人間からの柔軟な操作インターフェースを実現しました。

背景: AIアシスタントの相互補完システム

OpenClawは強力なAIアシスタントですが、以下のような課題がありました:

  1. 不安定な状態の回復: 設定変更やトラブル発生時の自己修復
  2. 継続的な監視: 24時間のヘルスチェックとアラート
  3. 人間とのインターフェース: Discordやモバイルからの直感的な操作

これらの課題を解決するために、OpenClawを補助するClaude Codeセッションを常駐化し、相互に監視・制御するシステムを構築しました。

構成図

graph TB
    subgraph "サーバ (a10)"
        O[OpenClaw Gateway] -->|スキル管理| TM[tmux セッション
claudecode-discord] TM --> C[Claude Code
--channels server:openclaw-discord] C -->|remote-control URL| URL[https://claude.ai/code/session_XXX] end subgraph "リモートアクセス" DISC[Discord
#claude-claw] -->|/claudecode-bot コマンド| O IPH[iPhone Claude App] -->|ブラウザから
初回アクセス| URL IPH -->|セッション一覧| SESH[セッション管理画面] end TM -->|管理コマンド| MNG[OpenClaw スキル
start/stop/restart/status]

構築内容

1. ClaudeCodeBot-a10の概要

役割: OpenClawの補助・管理

  • OpenClawの設定変更やトラブルシューティングの支援
  • Discordチャンネルでの指示受け取りと実行
  • 定期的なヘルスチェックとメンテナンス

2. claude --channels常駐方式の構成

従来のワンショット方式から常駐方式に変更:

tmux new-session -d -s claudecode-discord \
  'claude --channels server:openclaw-discord \
   --dangerously-load-development-channels server:openclaw-discord'

設定のポイント:

  • tmuxセッションを使用して端末接続が切れても継続
  • --channelsフラグで特定のDiscordサーバーに接続
  • 開発チャンネルも読み込むオプション付与
  • 起動時の確認プロンプトを自動応答

3. OpenClawスキルによるリモート管理

OpenClawのスキルとしてclaudecode-botを実装し、Discordから直接管理可能にしました:

# Discordでのコマンド例
/claudecode-bot status    # 稼働状態確認
/claudecode-bot start     # 起動
/claudecode-bot stop      # 停止  
/claudecode-bot restart   # 再起動

スキルの特徴:

  • tmuxセッションの状態を自動検出
  • 起動時の確認プロンプトを自動応答
  • エラーハンドリングとログ取得
  • ユーザーフレンドリーな日本語応答

4. remote-controlでアプリから操作できる仕組み

Claude Codeのremote-control機能を活用:

  1. 自動URL生成: Claude Code起動時にremote-control URLが表示される
  2. 初回アクセス: ブラウザでこのURLを開くとiPhone Claudeアプリのセッション一覧に登録
  3. 常時接続: 以後はアプリから直接セッションに接続可能
# remote-control URLの例
https://claude.ai/code/session_abc123def456?token=xyz789

5. iPhoneアプリとの連携

セットアップ手順:

  1. Claude Codeを起動しremote-control URLを取得
  2. iPhoneのブラウザでURLを開く
  3. 「Claudeアプリで開く」を選択
  4. セッション一覧にClaudeCodeBot-a10として表示される
  5. 以後はアプリから直接操作可能

メリット:

  • モバイルからもOpenClawの補助AIにアクセス可能
  • セッション状態が維持される(コンテキスト保持)
  • 通知やアラートの受信が可能

技術的詳細

tmuxセッション構成

# セッション起動スクリプト(自動応答付き)
tmux new-session -d -s claudecode-discord \
  'claude --channels server:openclaw-discord \
   --dangerously-load-development-channels server:openclaw-discord' && \
sleep 3 && tmux send-keys -t claudecode-discord "1" Enter && \
sleep 3 && tmux send-keys -t claudecode-discord "1" Enter

OpenClawスキル実装

~/.openclaw/workspace/skills/claudecode-bot/SKILL.mdに管理ロジックを実装:

---
name: claudecode-bot
description: Manage the ClaudeCodeBot-a10 Claude Code session
---

# ClaudeCodeBot-a10 セッション管理

## 状態確認
tmux list-sessions | grep claudecode-discord

## 起動・停止・再起動
自動的にtmuxセッションを制御

セキュリティ考慮事項

  1. 環境変数使用: APIトークンは環境変数で管理
  2. 制限付きアクセス: 特定のDiscordチャンネルのみ許可
  3. 監視ログ: tmuxセッションの出力を定期的に監視

運用メリット

相互補完システムの効果

項目 効果 実現機能
相互監視 一方がダウンしても他方で再起動可能 自己修復システム
コンテキスト維持 長期的なプロジェクト管理が可能 継続的な作業フロー
多様なインターフェース ユーザーの状況に合わせた操作 Discord + モバイルアプリ
常時待機 即時応答による迅速なトラブル対応 24時間監視体制
メンテナンス相互補完 OpenClawの不安定状態をClaude Codeで修復 相互依存関係

実際のユースケース

  1. 深夜の緊急対応: モバイルからOpenClawのトラブルシューティングを指示
  2. 定期的なメンテナンス: ヘルスチェックとログ監視の自動化
  3. プロジェクト管理: 長期的な開発プロジェクトのコンテキスト維持
  4. チーム連携: Discordチャンネルを通じた複数メンバーからの指示受け付け

トラブルシューティング

よくある問題と解決策

  1. tmuxセッションが見つからない
    # セッション一覧確認
    tmux list-sessions
    
    # 強制再起動
    tmux kill-session -t claudecode-discord 2>/dev/null
    /claudecode-bot restart
    
  2. remote-control URLが表示されない
    • Claude Codeの起動ログを確認
    • tmux capture-pane -t claudecode-discord -p | grep -E "remote-control|Listening"
    • ネットワーク接続を確認
  3. iPhoneアプリにセッションが表示されない
    • 初回アクセスでブラウザからURLを開く必要あり
    • 「Claudeアプリで開く」オプションを選択
    • アプリの再起動を試す

まとめ

ClaudeCodeBot-a10システムの構築により、以下の相互補完関係を実現しました:

  1. 相互監視・制御: OpenClawの不安定状態をClaude Codeでメンテナンスし、Claude Codeの再起動をOpenClawで実行
  2. 多様な操作インターフェース: Discordを通じた人間とのコミュニケーションと、Remote Control機能によるモバイルオペレーション
  3. 常駐化による安定性: コンテキスト維持と即時応答可能な常駐システム
  4. 自己修復システム: AIアシスタント同士の協調による高い信頼性

この構成は、AIアシスタント同士の相互補完と、人間との柔軟なインタラクションを両立する効果的なパターンとして、同様のユースケースに適用可能です。


最終更新: 2026年5月3日構成バージョン: Claude Code 2.1.126 + OpenClaw 2026.4.x + tmux 3.3a


  1. a10というのは動いてるサーバの名前です。他にもClaudeCodeBotが居るので後ろに-サーバ名書いてます。 

RTX 3060 12GBでローカルLLMを動かしてみた正直な感想

自宅サーバーにローカルLLM環境を構築してみた。結論から言うと、RTX 3060 12GBではプログラム開発用途としては厳しいというのが率直な感想だ。

構成

  • CPU: AMD Ryzen 5600X
  • RAM: 16GB
  • GPU: NVIDIA RTX 3060 12GB
  • OS: Ubuntu 24.04.4 LTS
  • 推論エンジン: Ollama
  • 自律エージェント: OpenClaw

やったこと

OllamaでQwen3やQwen3.5などのモデルを動かし、OpenClawという自律AIエージェントと組み合わせて、Discord経由で指示を出せる環境を作った。Claude CodeをボスとしてOpenClawに作業を振るという構成だ。

ブログ記事の自動投稿、Redmine連携のスキル化、Samba共有の設定など、いくつかのタスクを実際にやらせてみた。

壁にぶつかったこと

VRAMとコンテキストの綱引き

最初はQwen3 14Bを使っていたが、モデルだけで9.3GBのVRAMを消費する。残りはわずか2〜3GBで、コンテキストウィンドウ(会話の記憶量)を32K確保しようとするとほぼ限界になる。

推論が遅くなり、60秒のタイムアウトで落ちるケースが頻発した。

コンテキストが足りないとエージェントが動かない

OpenClawはデフォルトで131Kトークンものコンテキストを要求する。12GBのVRAMではそんな量は到底乗らないため、GPU→CPU→タイムアウトという連鎖が起きる。

設定で8192に絞るとGPUで動くようになったが、今度はOpenClaw自体が「コンテキストが小さすぎる(min=16000)」とブロックしてくる。

最終的にQwen3.5 9Bに切り替えて64Kコンテキストで落ち着いたが、それでも複雑なタスクでは処理が60秒を超えてタイムアウトする。

自走はするが遅い、落ちる

シンプルな会話や軽いタスクはこなせる。ただし:

  • 複雑な指示(「Redmineに接続するスキルを作って」など)は途中で止まることが多い
  • エラーが起きてもDiscordに何も言わずに沈黙することがある
  • 1つのタスクに数分〜10分かかる

実用ラインには届いていない、というのが正直なところだ。

かかったコスト感

RTX 3060 12GBのグラボ自体は中古で3〜4万円程度。電気代も24時間稼働させるとそれなりにかかる。

一方でClaude APIのコストは、個人利用レベルなら月数百〜数千円で十分なコンテキストと速度が使える。

コスパで考えると、現時点ではクラウドAPIに軍配が上がる。

じゃあ意味がなかったか?

そんなことはない。

  • プライバシーを気にするデータを扱える
  • ComfyUIと組み合わせた画像生成など、LLM以外の用途にも使える
  • 「自分のサーバーで動く自律エージェント」というロマンは確かにある

ただ、「ローカルLLMでプログラム開発を全部まかなおう」という期待は12GB程度では難しいというのが今回の結論だ。

24GBや48GBのVRAMがあれば話は変わってくるかもしれない。あるいは、もう少しモデルの進化を待つのが現実的かもしれない。

まとめ

用途 RTX 3060 12GBでの実用度
雑談・簡単なQ&A △ 動くが遅い
文章生成・ブログ執筆 △ 可能だが時間がかかる
プログラム開発補助 ✗ タイムアウトが多く実用的でない
画像生成(ComfyUI) ○ こちらは十分実用的
プライベートデータの処理 ○ 用途次第でアリ

ローカルLLMはまだ趣味PCで気軽に使える状態ではないかな。今、メモリ不足で値上がりしているが、ちょっとすれば価格も落ち着いて構成の低価格なハードが出てくるのでは。と期待している。


この記事はClaude Codeが執筆し、私が修正しています。

AIが環境を作り、AIが記事を書いた話 – Claude CodeによるローカルLLMサーバー構築

はじめに

この記事は少し変わった経緯で生まれました。

AIコーディングアシスタントの Claude Code が、ユーザーと対話しながら自宅サーバーにローカルLLM + 自律AIエージェント環境を構築しました。そして構築完了後、「今回やったことをブログに書いて」という指示を受け、ローカルで動いている Ollama(coder7b-agent) が記事の下書きを生成し、Claude Code が WordPress REST API 経由で投稿したのがこの記事です。

つまり、AIが環境を作り、AIがその記事を書き、AIが投稿したというわけです。


Claude Code とは

Claude Code は Anthropic が提供する AI コーディングアシスタントです。ターミナルやエディタから直接操作でき、コードの読み書きだけでなく、SSH でリモートサーバーに接続してコマンドを実行したり、設定ファイルを変更したりと、かなり自律的に作業を進めてくれます。

今回はユーザーが「ローカルLLMサーバーを建てたい」と伝えると、Claude Code が計画を立てて実装まで主導しました。


構築した環境の概要

ハードウェア

項目 内容
OS Ubuntu 24.04 LTS
CPU AMD Ryzen 5600X
RAM 16GB
GPU RTX 3060 12GB VRAM

ソフトウェアスタック

レイヤー 選択 役割
推論バックエンド Ollama ローカルLLM実行エンジン
プライマリモデル Qwen3:14b 9.3GB VRAM、複雑タスク向け
フォールバック Gemma4-e4b-cpu CPU動作、VRAM競合時に自動切替
自律エージェント OpenClaw Discord統合、自律タスク実行
画像生成 ComfyUI SDXL-Turbo + Pony Diffusion V6 XL
Claude連携 MCP ブリッジ Claude Code ↔ Ollama / OpenClaw

Claude Code が実装した内容

1. Ollama のセットアップと VRAM 最適化

Claude Code が SSH でサーバーに接続し、Ollama をインストールしました。

curl -fsSL https://ollama.com/install.sh | sh

VRAM 最適化のため systemd の override 設定を作成しました。

[Service]
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"
Environment="OLLAMA_HOST=0.0.0.0"
Environment="OLLAMA_MAX_LOADED_MODELS=1"

Flash Attention と KV cache q8_0 の組み合わせで約30%のVRAM削減を達成し、RTX 3060 12GB で Qwen3:14b(9.3GB)を安定稼働させることができました。

2. モデル選定

Claude Code がユーザーとの対話でモデルを選定しました。最終的な構成:

Qwen3:14b(プライマリ)

  • VRAM: 9.3GB、複雑なタスクやコーディング支援に強い
  • OpenClaw が要求する 262K コンテキストを 8192 に制限する Modelfile を作成

Gemma4-e4b-cpu(フォールバック)

  • CPU 動作で VRAM を消費しない
  • Google の MoE アーキテクチャで実効 4B ながら高品質
  • ComfyUI で GPU が占有されているときに自動切替

3. OpenClaw 自律エージェント

OpenClaw は Discord を通じて自律的にタスクを実行できるエージェントです。Claude Code が設定ファイルを生成し、Discord ボットとの連携まで完了させました。

  • Discord でメンション(@llm-agent)するだけでタスクを指示できる
  • スレッド機能で案件ごとに会話を分けられる
  • openshell プラグインでシェルコマンドも実行可能

4. ComfyUI 画像生成

画像生成環境として ComfyUI をセットアップし、2つのモデルを導入しました。

  • SDXL-Turbo fp16: 高速生成(数ステップで生成可能)
  • Pony Diffusion V6 XL: 高品質生成(アニメ・イラスト向け)

重要な制約: Ollama と ComfyUI は VRAM を共有するため同時起動不可です。Gemma4-e4b-cpu フォールバックはこの制約への対応策でもあります。

5. MCP ブリッジの実装

Claude Code が自分自身と Ollama・OpenClaw をつなぐ MCP サーバーを実装しました。

mcp-ollama: Node.js で実装した MCP サーバー。ask_ollamalist_models ツールを提供します。この記事の下書きも、このブリッジ経由で Ollama に生成させています。

openclaw-mcp-serve.sh: SSH 経由で OpenClaw の MCP サーバーに接続するラッパースクリプト。nvm 環境を SSH 非インタラクティブ環境でも読み込めるよう工夫しました。


実装中のハマりポイント

Claude Code がぶつかった問題と解決策の記録です。

Discord webhook の bot-to-bot 制限

Webhook で送ったメッセージに OpenClaw が反応しない問題。Discord 仕様で bot は bot/webhook のメッセージを無視するためです。OpenClaw ネイティブの Discord ボット統合に切り替えて解決しました。

OpenClaw Web UI のアクセス制限

HTTPS または localhost しか許可されない仕様。SSH トンネルで回避しています。

ssh -L 18789:localhost:18789 llm
# → ブラウザで http://localhost:18789 にアクセス

nvm 環境が SSH 非インタラクティブで読まれない

MCP 経由で SSH 実行する場合、~/.bashrc が読み込まれないため nvm が使えません。ラッパースクリプトで source ~/.nvm/nvm.sh を明示的に実行することで対応しました。


この記事の生成と投稿について

「今回やったことをブログに書いて欲しい」というユーザーの指示を受け、Claude Code は以下のステップを実行しました。

  1. 記事生成: MCP ブリッジ経由で Ollama(coder7b-agent)に記事の下書きを依頼
  2. 投稿: WordPress REST API を使って直接 WordPress に投稿

ただし当初は色々と苦労しました。OpenClaw への指示はペアリング問題で断念し、Discord 経由の投稿はアクセス権限の問題で失敗。最終的に Ollama MCP + REST API という構成に落ち着きました。


まとめ

Claude Code がユーザーと対話しながら、計画・実装・ドキュメント化・投稿まで一気通貫でやり遂げた事例でした。

ローカル LLM 環境があることで、Claude Code がさらにその環境を活用して記事を書くという面白い構図が生まれました。プライバシーを守りながら自前の AI 基盤を持つことの可能性を感じさせる体験でした。

なお、RTX 3060 12GB という家庭用 GPU でも、VRAM 最適化を工夫すれば十分実用的な環境が構築できます。ローカル LLM に興味がある方はぜひ試してみてください。

SendGridからOCI Email Deliveryに乗り換えた話

** この記事はClaude Codeと作業した記録をClaude Codeに記事にてもらい、Claude in Chromeを通してClaude Codeが投稿しています。 **

自宅サーバで長年お世話になっていたTwilio SendGridのFreeプランが、2026年3月31日で終了することになりました。4月1日から60日間のトライアルに移行し、5月末にはメール送信が止まってしまうとのこと。

うちのサーバではPostfix経由でSendGridを使って、Redmineの通知メールを飛ばしたり、lambeden.jpに届いたメールをGmailに転送したりしていました。さてどうしましょうか。

OCI Email Deliveryを選んだ理由

うちのサーバはOracle Cloud Infrastructure(OCI)のAmpere A1インスタンスで動いています。OCIにはEmail Deliveryというメール配信サービスがあって、月3,000通まで無料で使えます。同じプラットフォーム内で完結するので、これが一番スマートな選択肢かなということで移行してみました。

Claudeに手順を聞きながら作業しました (^_^)/

OCI Email Deliveryの設定

1. SMTP資格証明の生成

OCIコンソールで「アイデンティティ」→「ドメイン」→「Default」→「ユーザー」から自分のユーザーを開いて、SMTP資格証明を生成します。

⚠️ 生成されたユーザー名とパスワードはその場でコピー必須。画面を閉じると二度と確認できません!

2. 承認済み送信者の登録

「開発者サービス」→「電子メール配信」→「承認済送信者」で、メールのFromアドレスとして使うアドレスを登録します。

3. SPFの設定

承認済送信者の画面から「SPFの表示」でTXTレコードを確認して、お名前.comのDNS管理画面に追加します。

v=spf1 include:ap.rp.oracleemaildelivery.com ~all

4. DKIMの設定

「電子メール配信」→「電子メール・ドメイン」でドメインを作成して「DKIMの追加」からCNAMEレコードを生成、DNSに追加します。セレクター名はmail-tokyo-20260305みたいな形式が推奨されています。

10〜30分待って「Refresh DKIM Status」でActiveになれば完了です。

5. Postfixの設定変更

/etc/postfix/main.cfのリレーホストをOCIに変更します。

relayhost = [smtp.email.ap-tokyo-1.oci.oraclecloud.com]:587

/etc/postfix/sasl_passwdの認証情報も更新。

[smtp.email.ap-tokyo-1.oci.oraclecloud.com]:587    SMTPユーザー名:パスワード

あとSMTPUTF8関連のエラーが出たのでmain.cfに以下も追加しました。

smtputf8_enable = no

反映して動作確認。

sudo postmap /etc/postfix/sasl_passwd
sudo systemctl reload postfix
echo "テスト" | mail -s "テスト" -r xxxx@lambeden.jp 宛先アドレス

Redmineの通知メールもバッチリ届くようになりました。

問題発覚:転送メールが弾かれる

実はlambeden.jpに届いたメールをGmailに転送する設定もしていて、ここでハマりました。

OCI Email DeliveryはエンベロープFromとヘッダFromの両方が承認済み送信者に登録されていないと拒否する仕様です。転送メールの場合、Fromは外部の不特定の送信者になるので、これは構造的にどうにもなりません。

解決策:転送だけGmail SMTPを使う

PostfixのTransport Mapsで、自分のGmailアドレス宛の転送メールだけGmailのSMTPサーバー経由で送るようにしました。

/etc/postfix/transportに追記:

xxxx@gmail.com    smtp:[smtp.gmail.com]:587

/etc/postfix/sasl_passwdにGmailのアプリパスワードを追記:

[smtp.gmail.com]:587    xxxx@gmail.com:アプリパスワード

/etc/postfix/main.cfにtransport_mapsを追加:

transport_maps = hash:/etc/postfix/transport

反映して動作確認:

sudo postmap /etc/postfix/transport
sudo postmap /etc/postfix/sasl_passwd
sudo systemctl reload postfix

iCloudからlambeden.jpにテストメールを送ったら、ちゃんとGmailに届きました!GmailはFromを自分のGmailアドレスに書き換えますが、X-Google-Original-Fromヘッダに元の送信者が保持されるので実用上問題ありません。

まとめ

最終的なPostfixの構成はこうなりました。

用途 経路
Redmine通知・外部への送信 OCI Email Delivery
Gmailへの転送 Gmail SMTP

OCI Email Deliveryは同じプラットフォーム内で完結するので管理が楽で良いですね。SendGridよりも設定の自由度が低い部分もありましたが、無事移行できて一安心です。

GOGETSSLからLet’s Encryptに乗り換え

今までGOGETSSLの証明書を使っていましたが、更新期限が来たのと、今後、証明書の期限が200日以内になるという話もあるので、これを機にLet’s Encryptに乗り換えてみました。

Let’s Encryptは無料で使えますが、有効期限が90日なので、自動更新でもしないとやってられません。はい。自動更新の仕組みあります(^^;

今回は、Claude Codeに手順を出してもらって実施しました。完璧に動きました。すごい。(操作も含めて実行してもらうこともできるのですが、ちょっと怖かったので手順を出してもらって自分で事項しましたが、全く問題ありませんでした。本当にびっくりです。)

手順は以下の通り

Let’s Encrypt SSL証明書の自動更新(Apache + Postfix)

1. Certbot のインストール

# Ubuntu/Debian
sudo apt update
sudo apt install certbot python3-certbot-apache

# RHEL/CentOS/Rocky Linux
sudo dnf install certbot python3-certbot-apache

2. Apache 用の証明書取得

# Certbot が Apache の設定を自動的に更新する場合
sudo certbot --apache -d example.com -d www.example.com

# 証明書のみ取得(Apache 設定は手動)
sudo certbot certonly --apache -d example.com -d mail.example.com

mail.example.com を Postfix 用に同じ証明書に含めることを推奨

3. Postfix の SSL 設定

sudo nano /etc/postfix/main.cf
# TLS 設定
smtpd_tls_cert_file = /etc/letsencrypt/live/example.com/fullchain.pem
smtpd_tls_key_file  = /etc/letsencrypt/live/example.com/privkey.pem
smtpd_tls_security_level = may

smtp_tls_cert_file = /etc/letsencrypt/live/example.com/fullchain.pem
smtp_tls_key_file  = /etc/letsencrypt/live/example.com/privkey.pem
smtp_tls_security_level = may
sudo systemctl reload postfix

4. 自動更新の設定(重要)

Certbot はインストール時に systemd タイマーまたは cron を自動登録します。確認:

# systemd の場合
sudo systemctl status certbot.timer
sudo systemctl enable certbot.timer

# cron の場合(/etc/cron.d/certbot が存在するか確認)
cat /etc/cron.d/certbot

5. 更新後フック(サービス自動リロード)

更新後に Apache と Postfix を自動リロードするフックを作成:

sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh
#!/bin/bash
# Let's Encrypt 更新後に Apache と Postfix をリロード

echo "Reloading Apache and Postfix after certificate renewal..."
systemctl reload apache2   # Ubuntu/Debian
# systemctl reload httpd   # RHEL/CentOS

systemctl reload postfix

echo "Done: $(date)"
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh

6. 動作テスト

# ドライランで更新をテスト(実際には更新しない)
sudo certbot renew --dry-run

# フックも含めてテスト
sudo certbot renew --dry-run --deploy-hook /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh

7. 証明書の状態確認

# 証明書一覧と有効期限
sudo certbot certificates

# Postfix の TLS 確認
openssl s_client -connect mail.example.com:25 -starttls smtp 2>/dev/null | openssl x509 -noout -dates

まとめ・ポイント

項目 内容
証明書の場所 /etc/letsencrypt/live/example.com/
自動更新タイミング 有効期限 30 日前(Certbot が自動判断)
フックの場所 /etc/letsencrypt/renewal-hooks/deploy/
更新頻度 1 日 2 回チェック(systemd timer)

ポイント:

  • Apache と Postfix で 同じ証明書ファイルを共有 できる
  • deploy/ フォルダのスクリプトは更新成功時のみ実行される
  • ポート 80 が外部から到達可能である必要がある(HTTP-01 チャレンジ)

ドメイン名や OS の種類を教えていただければ、より具体的な設定を出せます。

以上、本当にすごい時代になったものです。