codexteer 0.18.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,399 @@
1
+ const CONNECTION_MISMATCH = {
2
+ code: "CLOUD_TARGET_CONFLICT",
3
+ when: "--connectionの明示指定とタスクIDの種類が合わない。明示指定は自動で切り替えない。",
4
+ action: "エラー文の--connection(JSONはerror.expected_connection、指定値はerror.connection)で指定し直す。task_ IDはcloud、durable_ IDはdesktop-cloud、ローカルUUIDはshared。--connection cloudに別種IDを渡すと同じ情報をCLOUD_OPTIONS_INVALIDで返す。",
5
+ };
6
+ const CLOUD_LOGIN = {
7
+ code: "CLOUD_LOGIN_REQUIRED",
8
+ when: "公式Codex CLIがChatGPTでログインしていない、またはサーバーがHTTP 401を返した。",
9
+ action: "ユーザーに公式CLIでのChatGPTログインを依頼する。トークンや認証ファイルを探したり渡したりしない。",
10
+ };
11
+ const CLOUD_AUTH_NOTE = "認証はPATH上の公式Codex App Serverからメモリ内で取得する。認証ファイルを直接読まず、トークンを保存・表示しない。";
12
+ const CLOUD_COMMON_SUPERVISION = "監督登録・pause/resume/stop・指摘の重複介入防止・history check・指示の置換/撤回・カーソル監視はローカルと共通の実装を使う。";
13
+ const ATTEMPT_WEB_ONLY = "history show|check --attemptはWeb Cloud専用。Desktop Cloudではhistory check <TARGET> <MESSAGE-ID>で照合する。";
14
+
15
+ const ENV_VS_PROJECTS = "environments listはCloud実行環境構成、--connection desktop-cloud projects listはDesktopのプロジェクト一覧で、別物。";
16
+
17
+ const REMOTE_KEEP_ROUTE = "生成された--host・--remote-transport・--context-thread・--supervisor・--connectionを全コマンドでそのまま保持する。";
18
+ const REMOTE_ROUTES_SEPARATE = "native・control・pairedのカーソルと監督IDは交換できない。経路が違えばSTALE_CURSORまたはSUPERVISOR_MISMATCH。";
19
+ const REMOTE_NO_FALLBACK = "失敗しても別ホスト・別経路・UI・SSHへの自動切替や再起動はしない。";
20
+
21
+ export const topics = {
22
+ cloud: {
23
+ title: "Codex Cloud(Web)のタスクを共通の監督・観測・送信・指摘管理で扱う",
24
+ when: "chatgpt.com/codex/tasksのタスク(task_ ID・公式リンク)を作成・監督・観測・介入するとき。durable_ IDやhostId=durableリンクはhelp desktop-cloud、Desktop経由の別ホストはhelp remote。",
25
+ usage: [
26
+ "--connection cloud projects list",
27
+ "--connection cloud threads list [--limit N] [--cursor CURSOR] [--env ENV_ID]",
28
+ "--connection cloud thread create --project ENV_ID_OR_NAME [--branch BRANCH] [--dry-run] <MESSAGE...>|-",
29
+ "--connection cloud thread receipt <ATTEMPT_ID>",
30
+ "doctor --thread <CLOUD_TASK_ID|URL>",
31
+ "supervise <CLOUD_TASK_ID|URL> [POLICY] [--agent claude|codex] [--use-path-cli] [-- <AGENT_ARGS...>]",
32
+ "supervise status|pause|resume|stop <CLOUD_TASK_ID|URL>",
33
+ "read <CLOUD_TASK_ID|URL> [--since CURSOR] [--include-output]",
34
+ "watch <CLOUD_TASK_ID|URL> [--stream --notify digest|all] [--since CURSOR]",
35
+ "send <CLOUD_TASK_ID|URL> <MESSAGE...>|- [--new-turn] [--based-on CURSOR] [--finding ID]",
36
+ "history list|show|check|mark <CLOUD_TASK_ID|URL> ...",
37
+ "history show|check <CLOUD_TASK_ID|URL> --attempt <ATTEMPT_ID>",
38
+ "instructions list|retract <CLOUD_TASK_ID|URL> ...",
39
+ "findings create|list|show|resolve|dismiss|reopen|evaluate|stats <CLOUD_TASK_ID|URL> ...",
40
+ "diff <CLOUD_TASK_ID|URL> [--attempt N]",
41
+ ],
42
+ options: [
43
+ { name: "<CLOUD_TASK_ID|URL>", text: "task_で始まるID、またはhttps://chatgpt.com/codex/tasks/<ID>。この形式なら--connection省略時もcloudを選ぶ。" },
44
+ { name: "--connection cloud", text: "タスクIDを取らないprojects list・threads list・thread create・thread receiptでは必須。" },
45
+ { name: "--project ENV_ID_OR_NAME", text: "thread createで必須。アクセスできる環境のIDか完全一致の名前で、1件に決まらなければCLOUD_OPTIONS_INVALID。" },
46
+ { name: "--branch BRANCH", default: "環境のリポジトリが1つならその既定ブランチ", text: "作成するタスクのGitブランチ。既定ブランチが1つに決まらない環境では必須。" },
47
+ { name: "--dry-run", text: "作成・送信をせず、計画または受付記録だけを返す。" },
48
+ { name: "--limit N(threads list)", default: "20", text: "1〜500。続きは応答のcursorを--cursorへ渡す。--envで環境IDに絞れる。" },
49
+ { name: "--new-turn", text: "停止中(completed/failed/cancelled)のタスクを新しいターンで再開する。ユーザーが再開を許可した場合だけ使う。" },
50
+ { name: "--attempt <ATTEMPT_ID>(history)", text: "sendの受付記録(UUID)を表示・照合する。照合は再送しない。" },
51
+ { name: "--attempt N(diff)", default: "公式CLIの既定", text: "表示するCloudの試行番号。1〜4。" },
52
+ { name: "--stream(watch)", text: "止めるまで監視を続ける。--until・--timeout-msとは併用できない。" },
53
+ { name: "--notify digest|all(watch)", default: "--streamありはdigest、なしはall", text: "digestと--settle-ms・--max-hold-msは--stream専用。" },
54
+ { name: "--timeout-ms N(単発watch)", default: "30000", text: "変化を待つ上限。" },
55
+ { name: "--poll-ms N(watch)", default: "5000", text: "Cloudへの照会間隔。" },
56
+ ],
57
+ returns: "読み取り系は共通のthread_id・status・events・cursor・has_more・配送履歴・監督状態。Cloudの実IDのまま扱い、Desktopへ接続しない。sendはdelivery_status・delivery_action(interrupt-and-follow-up/new-turn)・cloud_attempt_id・message_id。thread createはtask_id・url・attempt_id・creation_status。diffは記録済みパッチ、なければdiff_available:false。失敗は終了コード1、--jsonではok:falseとerror.code。",
58
+ errors: [
59
+ CONNECTION_MISMATCH,
60
+ CLOUD_LOGIN,
61
+ { code: "CLOUD_CLI_UNSUPPORTED", when: "thread create・threads list・diffで、公式CLIが0.157.1未満か必要なcloudサブコマンドを持たない。PATHにcodexがなければCLOUD_CLI_UNAVAILABLE。", action: "ユーザーに公式CLIの導入・更新を依頼する。代わりの経路は使わない。" },
62
+ { code: "CLOUD_TURN_AMBIGUOUS", when: "通常sendで実行中のターンが1つに決まらない(停止中のタスクを含む)。", action: "readし直す。停止中なら、ユーザーが再開を許可した場合だけ--new-turnで送る。" },
63
+ { code: "CLOUD_TASK_IDLE", when: "送信直前の再確認で、指定した親ターンが既に終わっていた。未送信。", action: "readし直す。再開はユーザーが許可した場合だけ--new-turn。" },
64
+ { code: "CLOUD_TASK_BUSY", when: "実行中のタスクへ--new-turnを指定した。", action: "--new-turnを外し、通常sendで実行中のターンへ送る。" },
65
+ { code: "CLOUD_STATE_CHANGED", when: "読んだ後にCloudのターンまたはユーザー入力が変わった。未送信。", action: "readし直してから介入するか判断する。" },
66
+ { code: "CLOUD_DUPLICATE_SEND", when: "同じタスクの前回送信が受付不明、または同じ親ターンへ受付済み。", action: "error.existing_attempt_idをhistory check <TASK> --attempt <ID>で照合する。再送しない。" },
67
+ { code: "CLOUD_RATE_LIMITED", when: "Cloudが429を返した。自動再試行はしていない。", action: "error.retry_after_ms以上待ってから読み直す。" },
68
+ { code: "CLOUD_CREATION_UNKNOWN", when: "作成後に一意のタスクIDを確定できなかった。", action: "thread receipt <ATTEMPT_ID>と--connection cloud threads listで確認する。自動で作り直さない。" },
69
+ { code: "CLOUD_CAPABILITY_UNSUPPORTED", when: "Cloudで未実装の操作を実行した。Desktopへの代替は試していない。", action: "その操作は使わず、必要ならユーザーに伝える。" },
70
+ ],
71
+ examples: [
72
+ "codexteer --connection cloud projects list --json",
73
+ "codexteer --connection cloud thread create --project env_example --branch main 'テストを追加してください' --json",
74
+ "codexteer supervise task_example --agent claude",
75
+ "codexteer read task_example --include-output --json",
76
+ "codexteer supervise pause task_example --json",
77
+ "codexteer history check task_example <MESSAGE-ID> --json",
78
+ "codexteer history check task_example --attempt <ATTEMPT-ID> --json",
79
+ ],
80
+ notes: [
81
+ "--connectionを省略するとtask_ ID・公式リンクからcloudを自動で選ぶ。",
82
+ "Cloudタスクに--host・--remote-transport・--context-threadを付けるとCLOUD_TARGET_CONFLICTで拒否する。",
83
+ "CloudタスクはDesktop UIへ自動でフォールバックしない。--backend uiはCLOUD_TARGET_CONFLICT。",
84
+ "PATH上の公式Codex CLIとChatGPTログインが必要。",
85
+ "thread create・threads list・diffは公式CLI(codex cloud)を使い、0.157.1以上であることを確認してから実行する。",
86
+ CLOUD_AUTH_NOTE,
87
+ "通常sendは実行中の親ターンを指定し、それを中断して同じタスクの後続ターンを始める。",
88
+ "送信直前に親ターンとユーザー入力の鮮度を再確認するが、サーバー側での原子的な固定は保証しない。",
89
+ CLOUD_COMMON_SUPERVISION,
90
+ "監督中は生成された--supervisorと--connection cloudを全コマンドで保持する。",
91
+ "pauseは送信を、stopは観測と送信を拒否する。",
92
+ "pause・stopはCloud上の作業自体を取り消さない。",
93
+ "watch --streamは止めるまで続き、既存Monitorのdigest・接続通知・復帰待ちを使う。",
94
+ "Cloudの応答は16 MiBが上限で、超えたら切り詰めずCLOUD_OUTPUT_LIMITで拒否する。",
95
+ "sendの本文はローカルと同じ私有ジャーナルに保存する。",
96
+ "受付(accepted)・履歴での保存確認(stored)・要求の達成はそれぞれ別の事実として扱う。",
97
+ "unknown・not_observedの配送は自動で再送しない。",
98
+ "未解決のCloud配送があると次の送信は止まるため、先にhistory checkで照合する。",
99
+ "checkpoint/resourceは明示したローカルの入力・成果物・コマンドだけを扱い、Cloudのファイルがマウントされているとは仮定しない。",
100
+ "thread createのモデル・タイトル・権限の上書き指定は未確認のため、無視せず拒否する。",
101
+ "作成結果はthread receipt <ATTEMPT_ID>、送信試行はhistory show|check --attemptで確認する。",
102
+ "照合(history check)は再送せず、対象タスクと監督状態を確かめる。",
103
+ ATTEMPT_WEB_ONLY,
104
+ "diff_available:falseはサーバーに記録済みのパッチがないだけで、変更ゼロの証明ではない。",
105
+ "詳細はdocs/cloud.md。",
106
+ ],
107
+ see: ["desktop-cloud", "connection", "supervise", "send", "watch", "history", "findings", "diff"],
108
+ },
109
+
110
+ "desktop-cloud": {
111
+ title: "Desktop Cloud(durable_ ID・hostId=durable)のタスクをCLIだけで作成・監督・送信する",
112
+ when: "DesktopのCloud環境構成で動くチャット(durable_ ID・hostId=durableリンク)を扱うとき。Desktopの起動やUI操作は不要。chatgpt.com/codex/tasksのtask_ IDはhelp cloud。",
113
+ usage: [
114
+ "--connection desktop-cloud environments list",
115
+ "--connection desktop-cloud projects list",
116
+ "--connection desktop-cloud threads list [--limit 1..100] [--cursor CURSOR]",
117
+ "--connection desktop-cloud thread create --environment ID_OR_EXACT_NAME [--title TEXT] [--dry-run] <MESSAGE...>|-",
118
+ "--connection desktop-cloud thread receipt <ATTEMPT_ID>",
119
+ "--connection desktop-cloud thread receipt <ATTEMPT_ID> --resolve-unknown --note TEXT",
120
+ "--connection desktop-cloud thread assign TARGET --project ID_OR_EXACT_NAME",
121
+ "--connection desktop-cloud doctor --thread TARGET [--project ID_OR_EXACT_NAME]",
122
+ "read|status|watch <DURABLE_ID|HOST_LINK> ...",
123
+ "send <DURABLE_ID|HOST_LINK> <MESSAGE...>|- [--new-turn]",
124
+ "history check <DURABLE_ID|HOST_LINK> <MESSAGE-ID>",
125
+ "history mark <DURABLE_ID|HOST_LINK> <MESSAGE-ID> --resolve-unknown --note TEXT",
126
+ "supervise <DURABLE_ID|HOST_LINK> [POLICY]",
127
+ "supervise prompt <DURABLE_ID|HOST_LINK> [POLICY]",
128
+ ],
129
+ options: [
130
+ { name: "<DURABLE_ID|HOST_LINK>(TARGET)", text: "durable_<UUID>、またはcodex://threads/<UUID>?hostId=durable。この形式なら--connection省略時もdesktop-cloudを選ぶ。" },
131
+ { name: "--environment ID_OR_EXACT_NAME", text: "thread createで必須。environments listのIDか完全一致の名前で、1件に決まらなければ拒否。" },
132
+ { name: "--title TEXT", text: "作成後にタスク名を設定する。1000文字以内。" },
133
+ { name: "--project ID_OR_EXACT_NAME", text: "thread assignで必須。doctorでは--threadと併用時だけ。thread createに付けると作成前にDESKTOP_CLOUD_PROJECT_UNAVAILABLE。" },
134
+ { name: "--limit N(threads list)", default: "20", text: "1〜100。続きは応答のnext_cursorを--cursorへ渡す。" },
135
+ { name: "--new-turn", text: "idleのタスクで新しいターンを始める。ユーザーが再開を許可した場合だけ使う。省略時は実行中のターン1つへexpectedTurnId付きで送る。" },
136
+ { name: "--dry-run", text: "作成・送信をせず、計画または受付記録だけを返す。" },
137
+ { name: "--resolve-unknown --note TEXT", text: "ユーザー専用。受付不明のまま確かめられないthread assignの試行(thread receipt)または送信(history mark)を、理由付きで解除する。--noteは必須。" },
138
+ ],
139
+ returns: "environments listは環境構成、projects listはDesktopのプロジェクト一覧。thread createはthread_id・deep_link・attempt_id・creation_status・delivery_status。thread assignはverification_status(verified以外は終了コード1)。thread receiptは作成の受付記録か所属割当の試行記録で、--resolve-unknownではresolution(by:user・at・note)付きの試行記録。doctorはready・observation・project_membership(membershipとassignment_api)・approval_roundtrip:unverified。read/watch/sendは共通の観測・配送形式。",
140
+ errors: [
141
+ CONNECTION_MISMATCH,
142
+ CLOUD_LOGIN,
143
+ { code: "STALE_OBSERVATION", when: "タスクの状態が送信の種類と合わない(通常sendで実行中のターンが1つでない、--new-turnでidleでない)。未送信。", action: "readし直す。idleの再開はユーザーが許可した場合だけ--new-turn。" },
144
+ { code: "DESKTOP_CLOUD_DELIVERY_PENDING", when: "同じチャットへの前回送信が受付不明(unknown)で未解除。error.existing_message_idがその送信。", action: "再送しない。history check <TARGET> <existing_message_id>で照合する。確かめられなければ送信を止めてユーザーに報告する。ユーザーはhistory mark <TARGET> <existing_message_id> --resolve-unknown --note TEXTで解除できる。" },
145
+ { code: "DESKTOP_CLOUD_PROJECT_UNAVAILABLE", when: "thread createに--projectを付けた(作成前に拒否)、Desktopの所属APIが対象タスクの実環境を受け付けない、またはthread receiptの試行IDが作成・割当のどちらの記録にもない。", action: "作成は--projectなしで行う。所属はdoctor --thread --projectで確認する。環境IDは差し替えない。receiptなら試行IDを確かめる。" },
146
+ { code: "DESKTOP_CLOUD_PROJECT_PENDING", when: "同じタスクへの前回のthread assignが受付不明で、Desktopの状態でも確かめられず未解除。error.existing_attempt_idとexisting_receipt_pathがその試行。", action: "再実行しない。--connection desktop-cloud thread receipt <existing_attempt_id>で再確認する。unknownのままならユーザーに報告する。ユーザーは同じコマンドに--resolve-unknown --note TEXTを付けて解除できる。" },
147
+ { code: "DESKTOP_CLOUD_OPTIONS_INVALID", when: "--resolve-unknownで--noteが空、または対象が未解除の受付不明(unknown)でない。Desktop Cloud経路の引数が不正なときも出る。", action: "thread receiptかhistory showでdelivery_statusとresolutionを確かめる。acceptedや解除済みなら解除は不要。" },
148
+ { code: "SUPERVISOR_CONTROL_FORBIDDEN", when: "--supervisor付きでprojects・environments・threads・thread(receipt・assign・--resolve-unknownを含む)やhistory mark --resolve-unknownを実行した。", action: "監督は担当タスクの観測と送信だけを行う。必要ならユーザーに端末から--supervisorなしでの実行を依頼する。" },
149
+ { code: "PROJECT_NOT_FOUND", when: "--projectが候補の1件に一致しない。", action: "projects listかdoctorの結果で正確なIDまたは名前を確かめる。" },
150
+ { code: "CAPABILITY_UNVERIFIED", when: "diffを実行した。Desktop Cloudの差分取得は未検証。", action: "read --include-outputのファイル変更イベントで確認する。" },
151
+ ],
152
+ examples: [
153
+ "codexteer --connection desktop-cloud environments list --json",
154
+ "codexteer --connection desktop-cloud thread create --environment example-config '接続を確認してください' --json",
155
+ "codexteer read 'codex://threads/aaaaaaaa-aaaa-4aaa-8aaa-000000000001?hostId=durable' --json",
156
+ "codexteer --connection desktop-cloud doctor --thread durable_aaaaaaaa-aaaa-4aaa-8aaa-000000000001 --project <PROJECT> --json",
157
+ ],
158
+ notes: [
159
+ "Web Cloudのtask ID・環境一覧とは別のサービス(codex-cloud-backend.chatgpt.com)に接続する。",
160
+ "接続先はdurable_ IDかhostId=durableリンクで保持する。",
161
+ "裸のUUIDからDesktop Cloudの宛先は推測しない。裸のUUIDはローカルのタスク。",
162
+ CLOUD_AUTH_NOTE,
163
+ "作成と--new-turnは、選択した環境構成と遅延起動指定(deferredEnvironment)を付けて送る。",
164
+ ENV_VS_PROJECTS,
165
+ "環境構成とDesktopプロジェクトへの所属は別の概念。",
166
+ "doctor --thread --projectは登録済みの所属(membership)と所属APIの可否(assignment_api)を分けて返す。",
167
+ "新しく割り当てるCloud環境へのプロジェクト付き作成は事前に拒否し、所属なしの作成を成功扱いしない。",
168
+ "thread assignはDesktopの署名付き所属APIを使い、実環境・nonce・署名・プロジェクトを照合し、保存結果まで確認する。",
169
+ "thread assignの対象は、そのDesktopの実行環境を使うチャットだけ。",
170
+ "通常のCloud実行環境で事前照合が拒否されても、環境IDの差し替えやローカル実行先の追加はしない。",
171
+ "受付不明のthread assignはthread receiptで確認し、自動で再送しない。",
172
+ "thread receiptとthread assignは受付不明の割当試行をDesktopのプロフィール状態で照合する(読み取りのみ)。",
173
+ "状態に同じプロジェクトのlocal割当(host_id:durable)が見えた試行はaccepted・verified(delivery_verification:desktop-profile-state)になる。",
174
+ "状態ファイルがない・読めない、別のプロジェクトや別ホストの割当では、試行はunknownのまま。見えないことは未適用の証明ではない。",
175
+ "--resolve-unknownで解除した割当試行は、同じタスクへの次のthread assignを止めない。delivery_statusはunknownのまま。",
176
+ "thread receiptの--resolve-unknownは所属割当の試行に使う。作成の受付記録には使えない。",
177
+ CLOUD_COMMON_SUPERVISION,
178
+ "履歴は上限付きで全ターンのページを取得するため、履歴が多いと遅くなる。",
179
+ "受付不明の送信は記録し、同じチャットへの次の送信をDESKTOP_CLOUD_DELIVERY_PENDINGで拒否する。",
180
+ "送信の保留は、history checkでstoredになるか、ユーザーがhistory mark --resolve-unknownで解除すると外れる。",
181
+ "--resolve-unknownは配送の有無を確定しない。delivery_statusはunknownのままresolutionを記録する。",
182
+ "サーバーがclientIdを記録しない場合、照合できるのは既知の受付ターンと本文の一致だけ。",
183
+ "履歴に見えないことは未送信の証明ではない。",
184
+ ATTEMPT_WEB_ONLY,
185
+ "承認の往復と差分専用APIは未検証。",
186
+ "通常のCloud実行環境へのプロジェクト登録は未対応。",
187
+ "詳細はdocs/desktop-cloud.md。",
188
+ ],
189
+ see: ["cloud", "environments", "connection", "projects", "thread", "supervise", "send", "history"],
190
+ },
191
+
192
+ environments: {
193
+ title: "Desktop CloudのCloud実行環境構成を一覧する",
194
+ when: "Desktop Cloudのthread create --environmentに渡すIDや名前を調べるとき。Desktopのプロジェクトは--connection desktop-cloud projects list、Web Cloudの環境は--connection cloud projects list。",
195
+ usage: ["--connection desktop-cloud environments list"],
196
+ options: [
197
+ { name: "--connection desktop-cloud", text: "必須。このコマンドはDesktop Cloud接続でだけ使える。" },
198
+ ],
199
+ returns: "environments[{id, name, scope(user/workspace), repository_ids}]、source:desktop-cloud-configurations、connection_mode:desktop-cloud。",
200
+ errors: [
201
+ CLOUD_LOGIN,
202
+ { code: "SUPERVISOR_CONTROL_FORBIDDEN", when: "--supervisor付きで実行した。", action: "監督は一覧できない。必要ならユーザーの端末で実行してもらう。" },
203
+ ],
204
+ examples: ["codexteer --connection desktop-cloud environments list --json"],
205
+ notes: [
206
+ ENV_VS_PROJECTS,
207
+ "userとworkspaceの両スコープを全ページ読み、1つの一覧にまとめる。",
208
+ "下書き(draft)の環境構成は一覧に含めない。",
209
+ ],
210
+ see: ["desktop-cloud", "cloud", "projects"],
211
+ },
212
+
213
+ remote: {
214
+ title: "Desktopに登録された別ホストのプロジェクト・チャットをCLIで観測・操作する",
215
+ when: "hostId付きリンクや--hostで別ホストのチャットを扱うとき。既定のnativeは観測専用。作成・一覧・new-turnは--remote-transport paired(登録はhelp remote-device)、既存activeターンへの送信はcontrol(help remote-control)。",
216
+ usage: [
217
+ "projects list --remote",
218
+ "projects list --all",
219
+ "--host HOST-ID projects list",
220
+ "--host HOST-ID --remote-transport paired projects list",
221
+ "--host HOST-ID --remote-transport paired threads list [--project ID] [--search TEXT] [--cursor CURSOR]",
222
+ "--host HOST-ID --remote-transport paired --context-thread LOCAL-UUID thread create --project ID|NAME <MESSAGE>",
223
+ "--host HOST-ID --remote-transport paired --context-thread LOCAL-UUID send <THREAD> <MESSAGE> --new-turn",
224
+ "read <HOST-LINK>",
225
+ "--host HOST-ID --context-thread LOCAL-UUID read <THREAD>",
226
+ "supervise <HOST-LINK> [--agent claude|codex]",
227
+ "supervise prompt <HOST-LINK> [--use-path-cli]",
228
+ ],
229
+ options: [
230
+ { name: "<HOST-LINK>", text: "'codex://threads/<UUID>?hostId=<URLエンコードしたHOST-ID>'。リンクのhostIdで対象ホストを選ぶ。裸のUUIDはローカル。" },
231
+ { name: "--host HOST-ID", text: "対象ホストを選ぶ。1回だけ指定する。リンクのhostIdと違えばHOST_MISMATCH。" },
232
+ { name: "--remote-transport native|control|paired", default: "native", text: "nativeは観測専用。controlは既存activeターンへの指定ターン送信。pairedは専用鍵で作成・一覧・new-turnまで扱う。" },
233
+ { name: "--context-thread LOCAL-UUID", text: "保存済みターンのある実在ローカルチャット。nativeの読取りとpairedの作成・new-turn・openで必要。Codex内ではCODEX_THREAD_IDを使う。" },
234
+ { name: "--remote / --all(projects list)", text: "--remoteはDesktopのリモート登録だけ、--allはローカルと併合する。" },
235
+ { name: "--project ID / --search TEXT / --cursor CURSOR(threads list)", text: "pairedのタスク一覧の絞り込みと続きの取得。ローカルでは使えない。" },
236
+ ],
237
+ returns: "projects listはリモート登録(host_id・source・availability)。read/watchは選択ホストの公開履歴差分とホスト別カーソル。データにはhost_id・remote_transportが付く。supervise promptのobservation_onlyはnativeでtrue、control/pairedでfalse。",
238
+ errors: [
239
+ { code: "HOST_MISMATCH", when: "リンクのhostIdと--hostが違う、またはDesktopが別のタスク・ホストの応答を返した。", action: "生成されたリンクと--hostをそのまま使う。ローカルや別ホストへ切り替えない。" },
240
+ { code: "REMOTE_READ_ONLY", when: "nativeで観測以外を実行した、またはcontrolで作成・一覧など送信以外の操作を実行した。未送信。", action: "観測だけにする。作成・一覧・new-turnはユーザーがpairedを、activeターンへの送信はcontrolを選んだ場合だけ。" },
241
+ { code: "REMOTE_CONTEXT_REQUIRED", when: "nativeの読取り、またはpairedの作成・new-turn・openで呼出し元がない。", action: "Codex内で実行するか、実在ローカルチャットを--context-threadで渡す。" },
242
+ { code: "REMOTE_CONTEXT_INVALID", when: "--context-threadがローカルの保存済みターンを持つチャットでない。", action: "保存済みターンのある実在ローカルチャットのIDを渡す。" },
243
+ { code: "HOST_CONNECTION_MISMATCH", when: "リモート対象に--connection desktopを指定した。", action: "--connectionを外す。リモートは選択した経路だけで観測する。" },
244
+ { code: "REMOTE_MANAGEMENT_TRANSPORT_REQUIRED", when: "paired専用の管理操作(open・Desktop購読等)をpaired以外で実行した。", action: "ユーザーが--remote-transport pairedを選んだ場合だけ実行する。" },
245
+ { code: "REMOTE_HISTORY_LIMIT", when: "公開履歴が100ページを超えた。部分スナップショットは返さない。", action: "ユーザーに報告する。" },
246
+ { code: "REMOTE_HOST_OPERATION_UNSUPPORTED", when: "desktop・debug-uiをリモートホストに対して実行した。", action: "ローカル専用の操作として扱い、リモートでは使わない。" },
247
+ ],
248
+ examples: [
249
+ "codexteer projects list --remote --json",
250
+ "codexteer --host remote-control:env_example --context-thread <LOCAL-UUID> read <UUID> --json",
251
+ "codexteer supervise prompt 'codex://threads/<UUID>?hostId=remote-control%3Aenv_example' --use-path-cli --json",
252
+ ],
253
+ notes: [
254
+ "nativeの読取りは既存shared wrapperの署名付きhelperと、Desktopのnative read_threadを使う。",
255
+ "nativeは実在ローカル呼出し元の保存済みターンを使うが、モデルの中継ターンや呼出し元への送信は発生しない。",
256
+ "公開履歴を10ターンずつ全ページ読み、100ページを超えたら止める。",
257
+ "コマンド出力・diffは項目ごとに最大20000文字まで読む。",
258
+ "Desktop側で省略された出力には[truncated by Desktop]を付けて明示する。",
259
+ "native監督本文は観測専用で、送信・再開・承認の代理回答を含まない。",
260
+ "control経路は既存の端末鍵が必要で、使えない環境では接続前に止まる。詳細はhelp remote-control。",
261
+ "control経路が使えるかは利用環境で確認が必要。",
262
+ "new-turn・作成はpairedだけ。native・controlでは使えない。",
263
+ "UI送信とオフライン修復(thread repair)はどの経路でもリモートに使えない。",
264
+ "pairedは作成・一覧・new-turn・checkpoint・resource・orchestrateに対応する。",
265
+ "pairedの作成・new-turn・openは実在ローカル呼出し元とDesktop公式APIが必要。一覧・読取り・指定ターン送信には不要。",
266
+ "pairedのnew-turnは対象チャットを制御側のDesktopに表示して購読する。",
267
+ "thread-shellはホストのfull accessで動く明示指定のbackendで、自動では選ばない。",
268
+ "Mac固有のdesktop・debug-uiはリモートホストに適用しない。",
269
+ REMOTE_KEEP_ROUTE,
270
+ "記録とロックはCODEX_HOME/codex-steer/hosts/<host-idのSHA256>/以下にホスト別に分ける。",
271
+ REMOTE_ROUTES_SEPARATE,
272
+ "supervise listは--hostで選んだホストの記録だけを返す。",
273
+ REMOTE_NO_FALLBACK,
274
+ "操作の詳細はdocs/remote-operations.md、観測と実機確認はdocs/remote-observation.md。",
275
+ ],
276
+ see: ["remote-device", "remote-control", "projects", "threads", "thread", "supervise", "connection"],
277
+ },
278
+
279
+ "remote-control": {
280
+ title: "Remote Control(--remote-transport control)で既存のactiveターンへ指定ターン送信する",
281
+ when: "別ホストで実行中のターンへexpectedTurnId付きで一度だけ指示を送る監督を、明示した直接接続で行うとき。観測だけならnative(help remote)、作成・new-turn・専用鍵はpaired(help remote-device)。",
282
+ usage: [
283
+ "--remote-transport control doctor --thread <HOST-LINK>",
284
+ "supervise <HOST-LINK> --remote-transport control [--agent claude|codex]",
285
+ "--remote-transport control supervise prompt <HOST-LINK> [--use-path-cli]",
286
+ "--remote-transport control read <HOST-LINK>",
287
+ "--remote-transport control send <HOST-LINK> <MESSAGE> [--based-on CURSOR] [--finding ID]",
288
+ ],
289
+ options: [
290
+ { name: "<HOST-LINK>", text: "hostId=remote-control:env_...のcodex://threadsリンク。remote-control:env_...以外のホストはREMOTE_HOST_UNSUPPORTED。" },
291
+ { name: "--remote-transport control", text: "全コマンドに付ける。--hostかhostId付きリンクが必要。--context-threadは不要。" },
292
+ { name: "--based-on CURSOR", text: "監督中のsendで必須。同じcontrol経路でreadしたカーソル。" },
293
+ { name: "--finding ID", text: "監督中のsendで必須。重複介入を防ぐ指摘ID。" },
294
+ ],
295
+ returns: "データにhost_id・remote_transportが付く。sendはApp Serverが同じturn IDで確認した受付状態。supervise promptのobservation_onlyはfalse。鍵の事前確認に失敗するとWebSocket接続前に止まり、doctorとエラーのremote_control_authに詳細を返す。",
296
+ errors: [
297
+ { code: "REMOTE_DEVICE_KEY_UNAVAILABLE", when: "登録済みの端末鍵を署名helperが使えない。ゲートウェイ接続と鍵の証明は行っていない。", action: "doctor --threadのremote_control_authを確認してユーザーに報告する。nativeの観測は別経路としてユーザーが選ぶ。" },
298
+ { code: "REMOTE_ENROLLMENT_REQUIRED", when: "一致する既存Desktopの端末鍵登録がない。codexteerは鍵を作らない。", action: "ユーザーにDesktop設定での登録を依頼する。専用鍵を使うならhelp remote-device。" },
299
+ { code: "REMOTE_AUTH_UNAVAILABLE", when: "有効な標準ChatGPTログイントークンがない。", action: "ユーザーに公式CLI/Desktopでの再ログインを依頼する。" },
300
+ { code: "REMOTE_AUTH_REJECTED", when: "ゲートウェイが認証を拒否した(HTTP 400はREMOTE_AUTH_UNSUPPORTED)。", action: "介入を止めて報告する。別経路へ切り替えない。" },
301
+ { code: "REMOTE_NEW_TURN_UNSUPPORTED", when: "controlで--new-turnを指定した。未送信。", action: "activeターンがない間は送らない。再開が必要ならユーザーにpairedを選んでもらう。" },
302
+ { code: "REMOTE_HOST_REQUIRED", when: "controlなのに--hostもhostId付きリンクもない。", action: "hostId付きリンクか--hostを指定する。" },
303
+ { code: "REMOTE_HOST_UNSUPPORTED", when: "hostIdがremote-control:env_...でない。SSHやCloudのホストは読み替えない。", action: "remote-control:env_...のリンクを使う。" },
304
+ { code: "REMOTE_IDENTITY_CHANGED", when: "接続中にアカウントまたは登録端末が変わった。別アカウントへは送っていない。", action: "介入を止めてユーザーに確認する。" },
305
+ ],
306
+ examples: [
307
+ "codexteer --remote-transport control supervise prompt '<hostId付きリンク>' --use-path-cli",
308
+ "codexteer --remote-transport control doctor --thread '<hostId付きリンク>' --json",
309
+ ],
310
+ notes: [
311
+ "現在のChatGPTログイントークンでwss://chatgpt.com/backend-api/codex/remote/control/clientへ認証する。",
312
+ "接続チャレンジには既存Desktop登録のOS非抽出キーで署名する。",
313
+ "新規登録・鍵作成・トークンのディスク保存はしない。",
314
+ "公式宛先以外への接続とリダイレクトは拒否する。",
315
+ "socket-refresh-v1、protocol v3、既存のDesktop端末鍵登録が必要。",
316
+ "未対応や認証拒否なら止まり、別経路へフォールバックしない。",
317
+ "サーバーがexpectedTurnIdを照合し、turn/steerは一度だけ送る。ターンが替わっていれば拒否される。",
318
+ "応答が不明な送信はunknownとして記録し、history checkで照合する。",
319
+ "再接続時にmutationを再送しない。",
320
+ "new-turn・resume・UI送信・承認の代理回答は未対応。",
321
+ "鮮度確認・pause/stop・指摘の重複防止・client message IDでの照合はローカルと同じく維持する。",
322
+ REMOTE_ROUTES_SEPARATE,
323
+ REMOTE_KEEP_ROUTE,
324
+ REMOTE_NO_FALLBACK,
325
+ "検証はテストと一時プロファイルの実同梱App Serverで行い、公式ゲートウェイの認証チャレンジ受信まで確認した。",
326
+ "既存端末鍵へのアクセスで止まっているため、control認証の完了・リモート読取・実配送は未検証。",
327
+ "調査根拠・実装と検証範囲はdocs/remote-control.md。",
328
+ ],
329
+ see: ["remote", "remote-device", "supervise", "send", "doctor", "history"],
330
+ },
331
+
332
+ "remote-device": {
333
+ title: "codexteer専用の端末鍵を公式に登録し、ホストとペアリングする",
334
+ when: "既存Desktopの鍵と分けた専用鍵で、許可したホストへ--remote-transport pairedで接続する準備をするとき。登録後の作成・一覧・new-turnはhelp remote。",
335
+ usage: [
336
+ "remote prepare [--key-provider keychain|openai-native]",
337
+ "remote enroll",
338
+ "remote status",
339
+ "remote identity",
340
+ "remote recover-key",
341
+ "remote verify",
342
+ "--host HOST remote pair --code-stdin",
343
+ "--remote-transport paired doctor --thread <HOST-LINK>",
344
+ "--remote-transport paired read <HOST-LINK>",
345
+ ],
346
+ options: [
347
+ { name: "--key-provider keychain|openai-native", default: "openai-native", text: "prepare専用。準備済みの鍵を別方式で置き換えず、方式を自動で切り替えない。" },
348
+ { name: "--host remote-control:env_...", text: "pairで必須。prepare・enrollには付けない。" },
349
+ { name: "--code-stdin", text: "pairで必須。ペアリングコードを標準入力から読む(TTYでは非表示)。" },
350
+ { name: "<HOST-LINK>", text: "hostId=remote-control:env_...のcodex://threadsリンク。" },
351
+ ],
352
+ returns: "registration_status(phase)・key_protection・key_provider・paired_host_ids・pairing_unknown・controller_name・instruction_sent:false。identityはserver_display_nameとname_matches。verifyはdevice-key認証と公式の許可ホスト一覧だけを確認し、チャットRPCを送らない。",
353
+ errors: [
354
+ { code: "SUPERVISOR_MISMATCH", when: "--supervisor付きでremoteコマンドを実行した。", action: "監督は登録・ペアリングをしない。ユーザーに依頼する。" },
355
+ { code: "REMOTE_STEP_UP_REQUIRED", when: "公式ブラウザでのfreshな本人認証が完了しない、古い、またはアカウント・スコープが合わない。", action: "ユーザーにブラウザ認証をやり直してもらう。" },
356
+ { code: "REMOTE_ENROLLMENT_PENDING", when: "前回の鍵作成・登録が途中または結果不明。", action: "鍵だけの中断はrecover-key、登録完了の有無はverifyで照合する。作り直さない。" },
357
+ { code: "REMOTE_PAIR_INPUT_INVALID", when: "pairで--hostがremote-control:env_...でない、--code-stdinの入力が長すぎる・中断された・形式が不正(英数字と-の6〜128文字でない)。ペアリングは送っていない。", action: "--host remote-control:env_...を付け、対象ホストで取得した新しいコードを標準入力で渡す。" },
358
+ { code: "REMOTE_PAIR_UNKNOWN", when: "前回のpairの応答が不明。", action: "remote verifyで照合してから次のpairを判断する。" },
359
+ { code: "REMOTE_PAIR_HOST_MISMATCH", when: "コードが選択したホストとは別のホストのものだった。チャットは開かず送信もしていない。", action: "ユーザーに正しいホストのコードを依頼する。" },
360
+ { code: "REMOTE_DEDICATED_ENROLLMENT_REQUIRED", when: "pairedで接続したが専用登録が完了していない。", action: "ユーザーにremote enroll・pair・verifyを依頼する。Desktopの鍵には切り替えない。" },
361
+ { code: "REMOTE_PAIR_REQUIRED", when: "pairedで接続したが対象ホストとのpairingがない。", action: "ユーザーにremote pair・verifyを依頼する。" },
362
+ { code: "REMOTE_KEY_PROVIDER_MISMATCH", when: "準備済みの鍵と別の--key-providerを指定した。", action: "既存の方式のまま使う。置き換えない。" },
363
+ { code: "REMOTE_KEY_HELPER_BUILD_FAILED", when: "keychain方式のhelperをビルドできない(Xcode command-line toolsがない)。鍵は作っていない。", action: "ユーザーにXcode command-line toolsの導入を依頼する。" },
364
+ ],
365
+ examples: [
366
+ "codexteer remote prepare --key-provider keychain --json",
367
+ "codexteer remote enroll --json",
368
+ "codexteer --host remote-control:env_example remote pair --code-stdin --json",
369
+ "codexteer --remote-transport paired doctor --thread '<hostId付きリンク>' --json",
370
+ ],
371
+ notes: [
372
+ "enrollは公式ブラウザでfreshな本人認証を求め、PKCE・state・アカウントとcodex.remote_control.enrollスコープを照合する。",
373
+ "パスワード・トークン・ペアリングコードをチャットや引数に渡さない。",
374
+ "keychain方式はXcode command-line toolsでcodexteer自身のhelperをビルドし、アドホック署名する。",
375
+ "keychain方式はOSが非抽出と報告するP-256鍵だけを使い、Secure Enclaveとは表示しない。",
376
+ "Desktopの署名やentitlementは変更しない。",
377
+ "openai-native方式は公式addonで新しい専用鍵を作る。",
378
+ "openai-native方式はハードウェアとOS権限に依存し、使えなければ止まる。",
379
+ "ペアリングコードは対象ホストのDesktop設定 → Connections → Control this PC → Addで取得し、Mac側のremote pair --code-stdinへ入力する。",
380
+ "対象ホストにCLIの追加インストールは不要。",
381
+ "公式CLIがある環境ではcodex remote-control pairも使える。",
382
+ "専用登録はCODEX_HOME/codex-steer/remote-deviceに保存し、Desktopの登録は更新しない。",
383
+ "秘密鍵・OAuth/bearer/remote-controlトークン・コード・証明はJSONに保存しない。",
384
+ "結果不明のときは同じ鍵とclientを保持し、作り直しやfinish・pairの自動再送をしない。",
385
+ "pairedは専用登録と対象ホストのpairingを必須とし、Desktopの鍵へフォールバックしない。",
386
+ REMOTE_ROUTES_SEPARATE,
387
+ "pairedでの作成・一覧・new-turn・検証の実行はhelp remoteとdocs/remote-operations.md。",
388
+ "UI送信と承認の代理回答は未対応。",
389
+ "登録・ペアリングはチャットの作成・送信の許可ではない。",
390
+ "利用者が指定したホストとチャットだけを対象にする。",
391
+ "remote statusのcontroller_nameはcodexteer_<OS>_<CPU>。",
392
+ "remote identityは同じ専用clientのサーバー表示名だけを照合する。",
393
+ "User-Agentに実際のOS/CPUを付ける。",
394
+ "Desktop側の任意名変更APIは未確認のため、controller_nameを画面上の名前とみなさない。",
395
+ "手順はdocs/remote-device-enrollment.md。",
396
+ ],
397
+ see: ["remote", "remote-control", "doctor"],
398
+ },
399
+ };
@@ -0,0 +1,10 @@
1
+ export const SUPERVISOR_STOPPED = { code: "SUPERVISOR_STOPPED", when: "停止済みの監督IDで登録・観測・送信した。またはstoppedの監督をpause/resumeした。", action: "その監督を終了する。停止済みIDは復活しないので、続けるならユーザーに新しい本文の生成を頼む。" };
2
+ export const SUPERVISOR_NOT_REGISTERED = { code: "SUPERVISOR_NOT_REGISTERED", when: "監督IDがこのタスクにまだ登録されていない。または未登録のタスクをpause/resume/stopした。", action: "本文の開始手順どおりsupervise registerしてから操作する。" };
3
+ export const SUPERVISOR_PAUSED = { code: "SUPERVISOR_PAUSED", when: "pause中の監督が送信した。", action: "送信しない。観測は続けられる。resumeはユーザーだけが行い、監督は自分で解除しない。" };
4
+ export const SUPERVISOR_ORPHANED = { code: "SUPERVISOR_ORPHANED", when: "superviseで直接起動した監督のプロセスが終了したのに、登録がactive/pausedのまま残っている。", action: "その監督を終了する。ユーザーにsupervise statusでの確認とstopを頼み、必要なら新しく始めてもらう。" };
5
+ export const NODE_VERSION_MISMATCH = { code: "NODE_VERSION_MISMATCH", when: "保存済みCLI方式の本文のコマンドを、生成時と違う版のNodeで実行した。", action: "介入を止めて報告し、使うNodeから本文を生成し直す。" };
6
+ export const RUNTIME_UNAVAILABLE = { code: "RUNTIME_UNAVAILABLE", when: "既定sharedの接続先(desktop startで起動する共有App Server)の実行記録やソケットが見つからない。", action: "doctorで確認してユーザーへ報告する。作業中のDesktopを終了・再起動しない。復旧(作業後にDesktopを終了してdesktop start)はユーザーが行う。" };
7
+ export const RUNTIME_NOT_READY = { code: "RUNTIME_NOT_READY", when: "共有App Serverの記録はあるが、そのプロセスかDesktopとの接続が生きていない。", action: "doctorで確認してユーザーへ報告する。作業中のDesktopを終了・再起動しない。復旧(作業後にDesktopを終了してdesktop start)はユーザーが行う。" };
8
+ export const DUPLICATE_INTERVENTION = { code: "DUPLICATE_INTERVENTION", when: "send --findingで、その指摘の同じrevisionにaccepted/unknownの送信がある(dry-runでも判定)。", action: "再送しない。error.existing_message_idをhistory checkして対応を待つ。新しい根拠か解決条件の変更があるときだけfindings reopenする。" };
9
+ export const OPTIONS_INVALID = { code: "OPTIONS_INVALID", when: "ローカル経路の引数が不正(未知のオプション、値の欠落・範囲外、IDやリンクの形式、必須引数の不足)。検証で止まり、送信もコマンド実行もしていない。", action: "error.messageとそのトピックのusage・optionsで引数を直して実行し直す。Cloud経路の同種のエラーはCLOUD_OPTIONS_INVALID、Desktop CloudはDESKTOP_CLOUD_OPTIONS_INVALID。" };
10
+ export const STORE_UNSAFE = { code: "STORE_UNSAFE", when: "CODEX_HOME/codex-steer/以下の記録やロックのファイル・ディレクトリが本人所有でない、group/otherに権限がある、シンボリックリンク、または種類が違う。", action: "自動修復しない。操作を止め、ユーザーに所有者と権限の確認を依頼する。" };