はじめに
この記事は、これから解説する仕組みそのものによって書かれています。Notionに書き溜めたネタを起点に、FreeBSDサーバー上のcronが定時にClaude Codeを非対話モードで起動し、記事の下書きを生成してGitにコミットする――その「ブログ自動投稿パイプライン」が、いままさにこの文章を出力しました。
発信は続ければ資産になりますが、ネタは溜まるのに執筆が続かない、というのは個人開発者にありがちな悩みです。本記事では、この問題を「ネタ出し(人間)」と「執筆(自動)」の分離で解こうとした構成を、実体験ベースで整理します。技術トピックのため、裏付けには査読付き論文ではなく公式ドキュメント・一次資料を用います。なお、無人でAIにコマンドを実行させる以上、安全性の論点は避けて通れないので、そこは誇張も省略もせずに書きます。
背景・課題
筆者の経験では、発信が止まる原因は着想の枯渇ではなく、一本を書き上げるまでの心理的・時間的コストにあります。ネタはメモに残るのに、清書する時間が取れずに腐っていく。だとすれば、自動化すべきは「何を書くか」ではなく「書く」という作業そのものです。
そこで本パイプラインは、創造的な判断が要る部分と、定型作業に落とせる部分を分けました。テーマの選定・切り口・読者設定といったネタ出しは人間がNotion上で行い、その一枚のカードを「ブリーフ(指示書)」として、執筆そのものを自動処理に委ねます。実際、この記事の元になったNotionカードには、想定読者・フック・見出し構成・トーンまで書かれており、人間の仕事はそこで完結しています。
ここで素朴な疑問が生じます。文章生成ならAPIを直接叩けばよいのでは、というものです。あえてコーディングエージェントであるClaude Codeを選んだ理由は、次節で述べます。
本論
なぜAPI直叩きではなくClaude Codeか
単に文章を生成するだけなら、言語モデルのAPIを呼べば済みます。それでもエージェントを選んだのは、ブログ生成が「文章を吐く」だけの作業ではないからです。リポジトリ内の既存記事を読んでトーンを揃え、フォーマット規約に従ってファイルを作り、Gitでコミットする――こうした「文脈を読む・ファイルを書く・ツールを実行する」が一連で必要になります。Claude Codeはファイルの読み書きやコマンド実行といったツールを備えたエージェント環境で、ユーザーが指示すれば自律的に探索・計画・実装を進めます(Anthropic, 2026b)。API単体では自前で実装する必要があるこの足回りを、標準で持っている点が決め手でした。
心臓部は非対話モード(claude -p)
無人実行の鍵が非対話モードです。公式ドキュメントによれば、claudeコマンドに-p(--print)を付けると対話UIなしで実行され、プロンプトを渡すとタスクを処理して結果を標準出力に出力します(Anthropic, 2026a)。CIやスクリプト、cronといった自動化に組み込むための入口で、出力形式はプレーンテキストのほか、結果やセッションID・メタデータを含むJSON、逐次ストリーミングのstream-jsonを選べます(Anthropic, 2026a)。本パイプラインは、この「一発実行・標準出力・自動終了」という挙動に乗っているだけ、と言ってもよいくらいです。
無人実行の代償――権限の線引き
ただし、ここに最大の注意点があります。Claude Codeは既定で、ファイル書き込みやコマンド実行など系を変更しうる操作のたびに許可を求めます(Anthropic, 2026b)。対話なら人間が承認すればよいのですが、無人実行では答える人間がいないため、確認プロンプトで止まること自体がバグになります。これを回避する乱暴な手段が--dangerously-skip-permissionsで、すべての確認を飛ばします。名前のとおり危険で、良性のファイル読み取りも破壊的なコマンドも区別なく素通りさせます。
正直に書けば、この全飛ばしは最後の手段です。公式ドキュメントが勧める安全側の作法はむしろ逆で、--allowedToolsで使ってよいツールを明示的に絞る、権限モード(dontAskや、危険な操作だけを別のモデルが判定して止めるautoモード)を使う、OSレベルのサンドボックスで隔離する、といった「絞る」方向です(Anthropic, 2026a; Anthropic, 2026b)。とりわけ無人実行では、許可ツールを限定することが「暴走したときの被害範囲」を決めます。スキップに頼るなら、ネットワークやファイルアクセスを制限した隔離環境に閉じ込めることが前提になる、と考えています。
FreeBSDという土俵で動かす
実行環境はFreeBSDです。トリガーはcronで、日本時間の19時に起動します。ここで地味に効くのがタイムゾーンで、サーバーがUTC運用だと「19時のつもりが朝4時」になりかねないため、起動時刻は明示的にJSTへ寄せています。
もう一つFreeBSDならではの事情があります。Claude CodeはFreeBSDネイティブのバイナリではないため、Linuxバイナリ互換機能(Linuxulator)経由で動かしています。Linuxulatorは未改変のLinuxバイナリをFreeBSD上でほぼネイティブのプロセスとして実行する仕組みで、現行で標準的に使われるのは Rocky Linux 9 系です(The FreeBSD Documentation Project, 2026a)。本環境もRocky Linux 9.7のユーザーランドを使っています。ただしcgroupsやnamespacesなど一部の機能は未対応とされており(The FreeBSD Documentation Project, 2026a)、Linux前提のサンドボックス手法はそのまま持ち込めません。ではどう隔離するか――その答えは後述するjailにあります。
生成された下書きはGitにコミットし、処理の成否はmsmtpでメール通知します。msmtpはsendmail互換のインターフェースを持つ軽量SMTPクライアントで、標準入力からメール本文を読み取ってSMTPサーバーへ送出します(marlam, n.d.)。無人処理は「黙って失敗する」のが最悪なので、結果が必ず手元に届く観測性を一本通しておく、という位置づけです。
隔離環境という発展形――jailとVNET
ここで、前述の「スキップに頼るなら隔離環境に閉じ込めることが前提」という話と、FreeBSDという土俵が地続きになります。Linuxであれば隔離の第一手はコンテナ(namespacesやcgroups)ですが、先述のとおりLinuxulatorはそれらを未対応としています。つまりLinux流のコンテナ隔離はそのまま持ち込めません。代わりに使うのが、FreeBSDネイティブの隔離機構であるjailです。jailは2000年のFreeBSD 4.0から存在し、Linuxのcgroupsより十年近く早く登場した、プロセスとファイルシステムをホストから隔離する仕組みです。公式ドキュメントによれば、ホスト側でLinuxバイナリ互換を有効にした上で、jailの中でLinuxバイナリを動かせます(The FreeBSD Documentation Project, 2026b)。jailはカーネルを持たずホストのカーネルを共有するため、Linux ABIの有効化はホスト側で行います。したがって、headlessで起動するClaude Codeそのものをjailに閉じ込めることができます。
隔離の効きどころは二つあります。ファイルシステムでは、jailのルートに「その仕事に必要な範囲」――たとえばブログのリポジトリだけ――を見せ、ホストの他の領域は存在しないものとして扱えます。こうしておけば、--dangerously-skip-permissionsで破壊的なファイル操作が素通りしても、被害はjailの外へ届きません。ネットワークでは、VNET(仮想ネットワークスタック)を割り当てたjailが、独自のIP・ルーティングテーブル・インターフェース・ファイアウォールを持ちます。jail内のpfで「AnthropicのAPIとgitリモートだけ許可、あとは破棄」と書けば、暴走した実行がデータをどこかへ送り出すことも、無関係なホストを覗くこともできなくなります。
整理すると、これは多層防御です。--allowedToolsが「エージェントが何を試してよいか」を絞り、jailが「試したところで何が起こりうるか」を絞る。全確認スキップという乱暴な選択が許容できるのは、壁がエージェントの善意ではなくjailの側にあるときだけ、という理屈です。
ただし正直に書けば、本パイプラインはまだここまではやっていません。jail+VNET+pfは相応の運用コストを伴い、専用ホスト上の非機微なブログ用リポジトリに対しては費用対効果が微妙な場面もあります。価値が出るのはむしろ、同じ枠組みを機微なリポジトリや、外部由来の入力を扱うタスクへ広げるときでしょう。なお実装上の小さな落とし穴として、ホストのrcスクリプトが用意するLinux用ファイルシステム(linprocfsなど)はjail内のLinuxプロセスには自動では効かず、fstabで明示的にマウントする必要があります。
実践への応用・考察
運用して分かったハマりどころを挙げます。第一に、前述の確認待ちです。headlessでは「テストも直しますか?」式の問いかけに応じる人間がいないため、対話前提の挙動はすべて事前に潰しておく必要があります。第二に、入力サイズです。公式ドキュメントによれば、パイプで渡す標準入力は10MBに制限されており(v2.1.128時点)、超えるとエラーで終了します。大きな入力はファイルに書いてパスを渡せ、とされています(Anthropic, 2026a)。第三に、バージョン間の挙動ドリフトです。ツールは更新で振る舞いが変わりうるため、無人運用ではバージョンを固定し、変化を意図的に取り込む運用が安全だと考えています。
効果としては、ともかく「発信が回る」ようになりました。一方で、品質保証は別問題です。本パイプラインはdraft: trueで下書きとして出力し、公開前に人間がレビューする前提にしています。公式ドキュメントも、AIには検証手段を与えよ、と説きます。同ドキュメントは、もっともらしく見えてもエッジケースを処理しない実装が出てくる失敗を「trust-then-verify gap」と呼び、対策としてテスト・スクリプト・スクリーンショットといった検証手段を必ず用意すること、検証できないものは出荷しないことを挙げています(Anthropic, 2026b)。裏を返せば、検証の仕組みを与えないかぎり「一見完了して見える」状態だけが頼りになり、結局は人間が最後の検証役を引き受けることになる——そう筆者は受け止めています。自動生成された文章も同じで、事実確認と最終判断は人間が握るべき、というのが現時点の結論です。
この枠組み自体は、ブログに限りません。Notionのカードをブリーフ、cronをトリガー、claude -pを実行系、Gitとメールを出力・通知系とする構造は、定期レポート生成やコード棚卸しなど、他の定型タスクへ横展開できる余地があります。
まとめ
- 発信が続かない問題を「ネタ出し(人間)」と「執筆(自動)」の分離で解く構成。Notionカードがそのままブリーフになる。
- 自動化の心臓部は非対話モード
claude -p。一発実行・標準出力・自動終了が自動化の入口になる(Anthropic, 2026a)。 - APIでなくエージェントを選んだのは、文脈を読み・ファイルを書き・ツールを実行する足回りが要るから(Anthropic, 2026b)。
--dangerously-skip-permissionsは全確認を飛ばす最後の手段。許可ツールの限定・権限モード・サンドボックスで「絞る」のが本筋(Anthropic, 2026a; 2026b)。- FreeBSDではLinuxulator(Rocky Linux 9系)経由で実行。タイムゾーン・入力サイズ上限・バージョン固定が実務上の勘所(The FreeBSD Documentation Project, 2026a; Anthropic, 2026a)。
- 品質は
draft: true+人間レビューで担保する。検証の最終責任は人間が握る(Anthropic, 2026b)。
そしてこの記事自体が、ここで説明したパイプラインの出力です。次の一本も、Notionのカードが一枚あれば、同じ仕組みが定時に書き始めます。
参考文献
公式ドキュメント
- Anthropic. (2026a). Run Claude Code programmatically (Headless). 2026年6月閲覧. https://code.claude.com/docs/en/headless
- Anthropic. (2026b). Best practices for Claude Code. 2026年6月閲覧. https://code.claude.com/docs/en/best-practices
- marlam. (n.d.). msmtp — an SMTP client. 2026年6月閲覧. https://marlam.de/msmtp/
- The FreeBSD Documentation Project. (2026a). FreeBSD Handbook: Chapter 12. Linux Binary Compatibility. 2026年6月閲覧. https://docs.freebsd.org/en/books/handbook/linuxemu/
- The FreeBSD Documentation Project. (2026b). FreeBSD Handbook: Chapter 17. Jails and Containers. 2026年6月閲覧. https://docs.freebsd.org/en/books/handbook/jails/