Codex で5分話した文が消えたので、文字起こしを自動でクリップボードへ写す常駐アプリを作った

by ZeroZawa

Codex のディクテーションで話した文は、入力欄から消えても手元の履歴ファイルに残っています。そこで、この履歴ファイルを見張り、新しい文字起こしを2秒後にクリップボードへ写す常駐アプリ「Codex Voice Clipboard」を作りました。入力欄が空になっても、Ctrl+V(Mac は ⌘V)で取り戻せます。

Windows 10/11 と Apple Silicon の macOS で動き、ソースとインストーラは GitHub で MIT ライセンスで公開しています。OpenAI とは関係のない非公式のツールです。

全体図。上の枠は Codex(ChatGPT デスクトップアプリ)で、話した内容がディクテーションで入力欄に入り、送信前に確かめて直せる。入力欄からは赤い点線で「送信前に消えた」へつながり、話した5分が画面から消える。話した内容は手元の履歴ファイル ~/.codex/transcription-history.jsonl へ1行追記される。Codex Voice Clipboard はこのファイルを読み取り専用で、増えた分だけ読み、新しい文字起こしを見つけたら2秒待って最新の1件だけをクリップボードへ写す。ほかは「最近10件」から手で選ぶ。クリップボードからは Ctrl+V か ⌘V でどこにでも貼って取り戻せる。下の帯には、Codex 本体には手を入れない、ネットワーク通信をしない、本文はログにも設定にも書かない、とある

5分話した文が、送信前に消えた

作ったきっかけは、Codex のディクテーションで5分ほど話した内容が、送信する前に入力欄から消えたことでした。かなり悲しかったです。

Codex のディクテーションは、入力欄(composer)で「Dictate」を選んで話すと、文字起こしが入力欄に入り、送信前に確かめて直せる、という機能です1。ライブの音声会話とは別で、話した内容をプロンプトの文にするところまでを受け持ちます2。送信前の文はまだ Codex に届いていないので、入力欄から消えると、話した5分ごと失ったように見えます。

実際には、文字起こしは消えていませんでした。Codex アプリにも履歴は残っています。ただ、5分話したあとにアプリの中の履歴まで取りに行くのは、とても面倒です。困ったのは「残っていない」ことではなく、「取りに行く手間」のほうでした。

このアプリを常駐させてからは、同じように入力欄が空になったときも、別の場所へ行かずに Ctrl+V だけで取り戻せました。

何をするアプリか

やることは1つで、新しい文字起こしを見つけたら、2秒待ってクリップボードへ写します。

起動するとタスクトレイ(Mac はメニューバー)にアイコンが出ます。アイコンはクリップボードにマイクを重ねた形で、色が3つあります。通常の色は監視中、琥珀色は自動コピーを止めている状態、赤は履歴ファイルが読めないかコピーに失敗した状態です。タスクバーが明るいか暗いかで、見やすい色の版に切り替わります。

Codex Voice Clipboard のアイコン一覧。左は濃い緑の角丸の地にクリップボードとマイクを白で描いたアプリのアイコン。右はトレイのアイコンで、明るいタスクバー用と暗いタスクバー用の2段に、監視中(自動コピー ON、黒または白)、一時停止中(自動コピー OFF、琥珀色)、エラー(履歴が読めない・コピー失敗、赤)の3つが並ぶ

メニューからは次のことができます。

  • 自動コピーを止める・再開する
  • 最新の文字起こし、または最近10件から選んですぐコピーする
  • コピーまでの待機時間を変える(0〜60秒、0.1秒刻み)
  • ログイン時の自動起動を切り替える(初期は OFF)
  • アプリが作ったものを消してアンインストールする

起動する前からあった履歴は、自動ではコピーしません。起動した瞬間に昔の文がクリップボードへ飛んでくると、そのとき持っていたコピーを黙って消してしまうからです。昔の文が要るときは、メニューの「最近10件」から選びます。

仕組み: 履歴ファイルを読むだけ

Codex 本体には手を入れず、Codex が手元に保存している履歴ファイルを読むだけです。流れは「増えた行だけ読む → 2秒待つ → 最新の1件だけ写す」の3段です。

ホワイトボードに描いた3段の図。左では Haru が長い紙のロールの、最後に増えた2行だけを虫眼鏡で読んでいる。中央では Haru が「2s」と出たストップウォッチを掲げて待っている。右では Haru が一番新しいカードだけを「Ctrl+V」と書かれたクリップボードに置き、古いカードは「RECENT 10」の箱へ入っていく

履歴ファイルは1行1件の JSON

ファイルは ~/.codex/transcription-history.jsonl です。私の Windows 機で中身の形を確かめると、1行が1件の文字起こしで、キーは id・createdAtMs(作成時刻のミリ秒)・text の3つでした。アプリが使うのは id と text だけです。形を合成した値で書くと、次のようになります。

{"id":"trial-1","createdAtMs":1794492256000,"text":"明日のミーティングの議題を三つにまとめて"}

このファイルの形式は公開された仕様ではありません。Codex の更新で形が変われば、このアプリは読めなくなります。README にもそう書いてあり、読めないときはアイコンが赤になります。

追記された分だけ読み、書きかけの行は待つ

履歴ファイルは追記されていくので、アプリは前回読んだ位置を覚えておき、増えた分だけを読みます。ファイルが作り直されたり短くなったりしたときは、ファイルの同一性と、読み終えた位置の直前64バイトを照らし合わせて気づき、最初から読み直します。

Codex が書いている途中の行(JSON が閉じていない、日本語の文字が途中で切れている)を読んでしまうこともあります。その行は捨てずに取っておき、次に読んだときに続きとつなげます。同じ id は2回コピーしません。

ファイルの変化は OS の変更通知で受け取り、それとは別に2秒ごとにも確かめます。変更通知が使えない環境でも、定期確認だけで動きます。

見つけてから2秒待ち、写すのは最新の1件だけ

新しい文字起こしを見つけたら、既定で2秒待ってから写します(待ち時間はメニューで0秒にもできる)。1回の読み取りで何件も見つかったときや、待っている間に次が来たときは、最新の1件だけを写します。ほかの文字起こしは「最近10件」から手で選ぶ形です。待ち時間は見つけた時点から数えるので、変更通知を取りこぼして定期確認で見つけた場合は、Codex が書いてから写すまで最大でおよそ4秒かかります。

私の Windows 機で、隔離した状態(後述の --sandbox)のアプリに合成した文字起こしを1件ずつ書き足し、クリップボード代わりのファイルが書き換わるまでの時間を5回測りました。どれも既定の2秒に0.1〜0.2秒ほど足した値でした。

TRIAL 1 ok=True ms=2171
TRIAL 2 ok=True ms=2125
TRIAL 3 ok=True ms=2156
TRIAL 4 ok=True ms=2141
TRIAL 5 ok=True ms=2141

このアプリはクリップボードを上書きします。待っている間にユーザーが別の物をコピーすると、その直後に文字起こしで上書きされます。避けられない性質なので、README の最初の注意に書き、初回起動時にも表示するようにしました。困る人は自動コピーを止め、必要なときだけメニューからコピーできます。一度写した文字起こしを繰り返し写すことはありません。

クリップボードは他のアプリが掴んでいて書けないこともあるので、失敗したら0.25秒おきに最大8回まで試し直します。それでも書けなければアイコンを赤にして、メニューから手動で再試行できるようにしています。

守ったこと: 通信しない、本文を残さない

このアプリは、ユーザーが話した文をクリップボードに流します。話した文には人に見せる前の下書きも混ざるので、本文の置き場所を2か所に絞りました。クリップボードと、メモリ上の最近10件だけです。

  • ログには時刻とイベント名(clipboard-copied など)だけを書き、本文は書かない
  • ネットワーク通信をしない(自動更新も付けない)
  • OS のクリップボード同期の設定には触らない(同期が有効なら本文が他の機器へ渡ることがある、と README に書いた)

この3つの約束は、口で言うだけでなくテストで確かめています。通信については、HTTP クライアントや自動更新の部品が Windows と macOS どちらのビルドにも入っていないことを、依存関係の一覧から調べるテストがあります。本文については、アプリを実際に動かしたあとのログと設定ファイルに、合成した本文が含まれていないことを確かめます。

アプリを実際に動かすテストは、本物のクリップボードや自動起動の設定には触れません。--sandbox <フォルダ> で起動すると、履歴・設定・クリップボード・自動起動の登録がすべてそのフォルダの中のファイルに置き換わります。テストはこの状態のアプリに合成した文字起こしを書き込み、16項目を確かめます。

上の5回の計測と、続けて書き足した3件の合わせて8件を写したあとのログは、次のとおりです。時刻とイベント名だけが並び、合成した本文はログにも状態ファイルにも1件も入っていませんでした。

2026-11-12T23:04:16.647+09:00 application-started
2026-11-12T23:04:16.762+09:00 state-active
2026-11-12T23:04:18.952+09:00 clipboard-copied
2026-11-12T23:04:22.090+09:00 clipboard-copied
2026-11-12T23:04:25.236+09:00 clipboard-copied
…(clipboard-copied があと5行)

公開している版を私の Windows 機でビルドし直してテスト一式を回すと、すべて通りました。Rust のテストが73件、ビルド設定や通信の有無を調べるテストが26件、実際にアプリを動かす統合テストが16項目です。

PASS old history is not copied on startup
PASS watcher plus two-second delay copies Japanese multiline Unicode
PASS duplicate record does not trigger copy
PASS transient clipboard adapter failures recover
PASS executed application logs and settings contain no transcript bodies
…(ほか11項目)
RESULT: 16 integration tests passed, 0 failed

Windows のインストーラは約2.3MB でした。

.NET で作って、その日のうちに Tauri 2 へ作り直した

最初の版は 2026年10月17日の午後に、C# と .NET で Windows 専用に作りました。その日の夕方には Tauri 2 で作り直しています。Mac でも同じものを使いたかったからです。

Tauri は、裏の処理を Rust で、画面を Web の技術で書くデスクトップアプリの枠組みで、トレイやメニューバーのアイコンとメニューも作れます3。作り直すときに、履歴の読み取り・コピーの予約・ログ・設定といった OS に依存しない中身を1つの部品にまとめ、トレイやクリップボードのように OS に触る部分は差し替えられる窓口を通すようにしました。--sandbox で本物のクリップボードの代わりにファイルを差し込めるのは、この分け方のおかげです。

.NET 版では、非同期の読み取りが重ならないように世代番号で管理していました。作り直した版では、状態を持つ処理を1本のスレッドが順番に呼ぶ形にして、その管理自体を要らなくしています。

使い方と注意

Releases から、Windows はインストーラ、Mac は .dmg を入れます。Codex でディクテーションを一度でも使い、履歴ファイルができていることが前提です。

どちらもコード署名をしていないので、初回だけ OS の警告を越える操作が要ります。

  • Windows: 「Windows によって PC が保護されました」で「詳細情報」→「実行」。管理者権限は要りません
  • macOS: 一度開いて警告を閉じたあと、システム設定の「プライバシーとセキュリティ」で「このまま開く」を押します。macOS 15 以降は、右クリック→「開く」では越えられません

使うときに気をつけることは3つです。

  • 待機中(既定2秒)に別の物をコピーすると、文字起こしで上書きされる
  • OS のクリップボード同期(Mac のユニバーサルクリップボード、Windows のクリップボード履歴やクラウド同期)が有効だと、本文が他の機器や履歴に渡ることがある
  • 履歴ファイルの形式は非公開なので、Codex の更新で動かなくなることがある(そのときは Issue で知らせてもらえると助かります)

ログイン時の実際の自動起動や、Releases から落とした .dmg を別の Mac で初めて開く流れは、まだ確かめ切れていません。README の「まだ確かめていないこと」に挙げてあります。

参考文献

Footnotes

  1. Prompting | ChatGPT Learn - Codex のディクテーションの使い方(composer で Dictate を選んで話す) ↩

  2. ChatGPT Voice | ChatGPT Learn - ディクテーションとライブ音声会話の違い ↩

  3. System Tray | Tauri v2 - Tauri 2 のトレイアイコンとメニュー ↩