AIエージェントと一緒に開発していて、こんな経験はありませんか。
「昨日の続きをお願い」と話しかけたら、エージェントが何も覚えていなかった。前回の方針も、残っていたTODOも、ブランチの状態も──全部リセット。また最初から説明する羽目になった。
ぼっち開発者がAIエージェントと組むとき、最大の壁は文脈の継続性です。この記事では、その問題をシンプルに解決するために導入した「セッション単位の開発フロー」と、それを支えるHANDOFF.mdという仕組みを紹介します。さらに、同じ思想の延長線上に作ったgit push一発の自動デプロイ環境についても後半で触れます。
ぼっち開発×AIエージェントに特有の課題
チーム開発では、文脈は複数の人間が分散して記憶しています。口頭での補完もあれば、PRのコメントが記録として残ることもある。でもぼっち開発では、過去の自分が唯一の情報源です。
そこにAIエージェントという相棒が加わると、独特の非対称性が生まれます。
- 未来の自分:細かいことは忘れるが、文脈を読めば思い出せる
- AIエージェント:細かいことは正確だが、セッションをまたぐと完全にリセットされる
この二者に対して同時に機能する引き継ぎの仕組みが必要でした。「未来の自分へのメモ」であり、かつ「次のセッションのエージェントへの指示書」でもあるもの。それがHANDOFF.mdです。
HANDOFF.md と AGENT.md ── 2つのファイルがセッションをつなぐ

リポジトリのルートに2つのファイルを常備しています。
AGENT.mdは、エージェントが守るべきルールをまとめた定義書です。言語(コミットメッセージや回答は日本語)、Gitの運用方針(セッションごとにブランチを作成)、コミットの粒度など、開発全体を通じて変わらないルールを記載しています。なおこの種のファイルは、最近はAGENTS.md(複数形)という命名が業界標準になりつつあります。OpenAIがCodexで推奨したことで広まった表記で、「複数のエージェント・複数のセッションに向けたルール集」という意味合いです。
HANDOFF.mdは、セッションをまたぐための引き継ぎメモです。「このセッションで何をしたか」「残っているTODO」「注意点・補足」を毎回記録します。
新しいセッションを開始するとき、エージェントはまずこの2つのファイルを読みます。HANDOFF.mdに「次回はこのブランチから継続する」と書いてあれば、そのブランチをcheckoutして作業を再開。そうでなければmainを最新にしてから新規ブランチを作成する──というルールです。
これだけで、AIエージェントとの作業が「毎回ゼロから始まる感覚」から「前回の続きから始まる感覚」へと変わりました。
HANDOFF.mdはエージェントが書く──自分ではほぼ一切書かない
ここで重要なのが、HANDOFF.mdを書くのはエージェント自身という点です。セッション終了時に、エージェントが自動で記述します。自分では書きません。
人間が書くと、疲れているときや急いでいるときは内容が雑になります。でもエージェントが書くなら毎回一定のフォーマット・一定の粒度で記録が残る。チーム開発でも難しいこのコンシステンシーが、ぼっち開発でも自然に実現されています。
さらに、HANDOFF.mdはGitのコミット履歴として残るので「あのセッションで何をしていたっけ」が後からでも追えます。ベクターDBやAPIを介した外部記憶システムと違い、Gitというすでにある仕組みの上に乗っているため、インフラの追加がゼロで済むのも大きなメリットです。
ぼっち開発者の役割は「判断」だけでいい
この仕組みが整うと、自分がやることは実質3つになります。
- 意思決定と方向性の提示──何を作るか、どう進めるか
- マージの最終判断──PRの内容を確認し、マージするかどうか決める
- セッションの開始と終了の宣言──エージェントに作業を依頼し、区切りをつける
コードもHANDOFFも書かない。そして実は、コードレビューもしません。
PRが作成されると、Gemini Code Assistが自動でコードレビューを行います。そのレビュー内容をAIエージェントが判断し、対応が必要であれば修正してスレッドコメントに対応内容を残す。対応不要と判断した場合はその理由をコメントに残す。レビューを鵜呑みにしないよう指示も出しているので、エージェントが主体的に取捨選択します。
自分がやることは、その一連のやり取りを確認したうえでマージするかどうかを決めるだけです。
これはある意味、エンジニアリングマネージャーに近い役割に自然に移行しているとも言えます。コードを書く人(エージェント)、レビューする人(Gemini Code Assist)、レビューに対応する人(エージェント)、最終判断する人(自分)──ぼっち開発なのに、チームのような分業構造が生まれています。
セッション開始から完了まで──具体的な流れ

ブランチ命名規則
ブランチはセッションごとに1本作成します。命名規則は以下の通りです。
dev/yyyymmdd-NNN-機能名(英語)
たとえば dev/20260222-001-add-deploy-workflow のように、日付・連番・機能名をつなぎます。同じ日に複数のセッションがあっても連番で区別でき、ブランチ一覧を見るだけで「いつ・何のために作業したか」が一目でわかります。
セッション開始の手順
まずHANDOFF.mdを確認します。「次回はこのブランチから継続する」という記載があれば、そのブランチをcheckoutして作業を再開。完了済みのセッションであれば、mainを最新にしてから新規ブランチを作成します。あわせてgit statusで未コミットの変更がないかも確認します。
開発・コミット
機能追加・修正・動作確認を進めながら、小さめのまとまりでコミットを積みます。コミットメッセージ・PRタイトル・PRコメントはすべて日本語で記述しています(ブランチ名のみ英語)。「何のために何を変えたか」が伝わることを最優先にしているからです。
セッション終了
「セッションを終了する」と宣言すると、エージェントが以下を順に実行します。
- 未コミットの変更があれば日本語メッセージでコミット
- HANDOFF.mdを更新──実施日・対象ブランチ・やったこと・残りTODO・注意点を記述
git push- PRを作成──タイトル・本文は日本語、変更内容とTODO抜粋を含む
コードレビューとPR対応
PRが作成されると、Gemini Code Assistが自動でコードレビューを行います。エージェントはそのレビュー内容を受け取り、対応が必要と判断した場合は修正してスレッドコメントに対応内容を残します。対応不要と判断した場合はその理由をコメントに残します。レビューを鵜呑みにしないよう指示も出しているため、エージェントが主体的に内容を取捨選択します。
自分はこのやり取りを確認するだけで、コードレビュー自体はしません。
マージと後処理
一連のやり取りを確認してマージを判断するのは自分の仕事です。マージしたら「マージ完了」と宣言するだけで、エージェントがgit checkout main && git pullを実行し、ローカルが最新のクリーン状態になります。
HANDOFFはMCPで置き換えられるのか?
「MCPを使えばいいのでは?」という発想は自然です。ただ、少し整理が必要です。
MCPは「ツールへのアクセス手段」であって、セッション間の文脈継続を直接解決するものではありません。GitHubのPR情報をリアルタイムで参照したり、外部サービスとの連携を標準化したりするのには優れていますが、「前回のセッションで何をして、何が残っているか」を把握するには結局どこかに状態を保存する仕組みが必要です。
つまり、MCPはHANDOFFの代替ではなく、組み合わせて使うものと考えるのが正確です。たとえばMCP経由でGitHub Issuesをリアルタイムに読み込み、それをHANDOFFと組み合わせてコンテキストを豊かにする、といった発展的な使い方も十分あり得ます。

おまけ:git pushで自動デプロイまで完結させる
開発フローが整ったら、デプロイも同じ思想で自動化しました。git pushの一言で、LAN上のMac miniが自動的に最新版へ更新される仕組みです。
なぜSSHをやめたのか
最初は「LAN上のMac miniへの反映はSSHでログインするしかない」と思っていました。でもデプロイのたびに「SSHして・pullして・再起動して」を繰り返すのは、小さいようで積み重なるとコンテキストスイッチのストレスになります。
GitHub Actionsのセルフホストランナーを使うことで、この作業をまるごと自動化できます。
セルフホストランナーの仕組み
「LAN内のMac miniにGitHubから接続できるの?」という疑問は自然ですが、仕組みは逆向きの接続です。
Mac mini側のランナーがGitHubに向けてポーリングし続け、ジョブが積まれると即座に受け取ってMac mini上で実行します。インバウンドのポートを開ける必要は一切なく、ファイアウォール内のマシンでもアウトバウンド接続さえあれば動作します。
さらに、セルフホストランナーは実行がMac mini上で行われるためGitHubのActions分数を消費しません。無料アカウントでも実質無制限で使えます。

ワークフローの構成(イメージ)
```yaml
on:
push:
branches: [main]
jobs:
deploy:
runs-on: self-hosted
steps:
- name: リポジトリの更新
run: git pull origin main
- name: 依存関係のインストール
run: pip install -r requirements.txt
- name: アプリの再起動
run: launchctl kick gui/$(id -u)/com.example.myapp
```
`runs-on: self-hosted`と書くだけで、Mac miniのランナーがジョブを拾います。pushからデプロイ完了まで早ければ数秒、遅くとも約1分以内です。runs-on: self-hostedと書くだけで、Mac miniのランナーがジョブを拾います。pushからデプロイ完了まで早ければ数秒、遅くとも約1分以内です。
初回セットアップの流れ
「最初だけは手動でやることがあるんでしょ?」──その通りです。ただし最初の一回だけです。

開発環境(手元のMac)
- リポジトリをclone
python3 -m venv venv→source venv/bin/activatepip install -r requirements.txt.env.exampleをコピーして.envを作成し、必要な環境変数を設定- アプリを起動して動作確認
Mac mini(一度だけ)
- cloneとvenvの作成・有効化、
pip install -r requirements.txt .envファイルの配置- アプリの待ち受けを
0.0.0.0に変更(LAN・VPN外からアクセスするため) - launchdでサービス登録し、自動起動・クラッシュ時再起動を設定
- GitHub Actionsセルフホストランナーのインストールとリポジトリへの登録
- デプロイ用ワークフローファイルをリポジトリに追加
この初回セットアップさえ終われば、以降はpushのみでデプロイが完結します。
ぼっち開発者がこのフローを使って感じたこと

最もよかったのは、「続きから始まれる」感覚が生まれたことです。セッションが変わっても、エージェントがHANDOFF.mdを読んで前回の文脈を把握してくれる。自分が「あれ、どこまでやったっけ」と迷う時間が激減しました。
そしてもう一つの気づきは、ぼっち開発なのにチームのような構造が自然に生まれていたということです。コードを書くエージェント、記録を書くエージェント、コードレビューをするGemini Code Assist、レビューへの対応を判断するエージェント、そして最終的な意思決定をする自分。気づけば完全にエンジニアリングマネージャー的な役割に移行していました。
一人で開発しているのに、誰かと組んでいるような感覚──これがぼっち開発者がAIエージェントと協業する面白さだと思っています。
このフローを支えるスタックをまとめると以下の通りです。
- Git + GitHub ── ソース管理と共有
- AGENT.md / HANDOFF.md ── エージェントとのセッション間記憶
- GitHub Actions + セルフホストランナー ── 無料でCI/CDを実現
- Mac mini ── 消費電力が低く常時起動に向いたローカルサーバー
- launchd ── macOSのサービス管理
- VPN ── LAN外からの安全なアクセス
大きなインフラ投資なしに、開発からデプロイまで快適に回せる環境はぼっち開発者にこそ向いていると感じています。


コメント