CLI のオプションを整える

3 つの課題が同じコードを書き換えるため、1 本にまとめて通す

📅 作成: 2026-09-01 / 更新: 2026-09-01

目次

  1. なぜ 1 本にまとめるか
  2. 決まっていること
  3. 選んだ形と、その理由
  4. 新しいオプション
  5. 段取り

なぜ 1 本にまとめるか

3 つの課題が、いずれも同じ 1 つの関数を書き換える。

課題変えるもの触る場所
i260831-02 AICHAT_ID--connector-id option()usage()
i260901-01 --retry-count 廃止 → --wait-min / --wait-hour option()usage()
i260901-02 AICHAT_URL--url / --port、短い形 option()usage()

別々に進めると、後の 2 件が前の書き直しになるoption()--名前 だけを探す作りで、短い形を入れるには別名の表を持つ形へ変える必要がある。3 件のうちどれを先にしても、この書き換えが 1 回目に含まれ、残り 2 件はその上に載る。

課題は 3 件のまま残す。計画だけを 1 本にする。課題は「何を解決するか」の単位、計画は「どう通すか」の単位であり、一致させる必要はない。

いま 1 行がどれだけ長いか

テスト用サーバーへ繋いで待受けを張ると、環境変数 2 つとオプション 2 つに分かれる。

$env:AICHAT_ID = 'ai-chat-lite'
$env:AICHAT_URL = 'http://localhost:8765'
node <ai-chat-lite>/src/client/chat.mjs wait --access-token 3f9c1e8a-... --retry-count 120

環境変数はプロセス一覧に出ない。待受けを 4 本起こして PID を照合しようとしたとき、Win32_ProcessCommandLine には node ...\chat.mjs wait しか出ず、どれがどれか起動時刻から推測するしかなかった。

決まっていること

項目決めたこと
--retry-count廃止する。回数は内部で決める
--timeout内部に隠す。呼ぶ側からは指定しない
待つ長さ--wait-min--wait-hour4808 はどちらも 8 時間)
両方を指定エラーにする。足さない・後勝ちにしない
上限なし0 を無限とする
既定値8 時間(いまは 480 秒)
ログ開始 1 行と終了 1 行だけ。240 秒ごとの「新着なし」は出さない
名乗る IDAICHAT_ID をやめ --connector-id にする。両対応にしない
接続先--url--port を足す。--portlocalhost のポートだけを指定する
短い形-c -a -r -p -u -w を付ける(-w--wait-hour
テスト用の指定--wait-sec を足す
--url--port の同時指定エラーにする
--connector-id の省略エラーにする。既定値を持たせない
AICHAT_URL廃止する
一覧の保ち方別名の表から usage() を組み立てる

なぜ引数にするのか

得られること中身
どれが誰か分かる コマンドラインに出る。環境変数はプロセス一覧に出ない
シェルを問わない bash でも PowerShell でも同じ 1 行。$env: / export / set の分岐が消える
取り違えが減る 環境変数は同じシェルに前の値が残る。引数なら毎回明示される

単位を名前に入れずに --wait としてはいけない。いま --timeout は秒なので、秒・分・時が混ざる。名前に単位があれば取り違えない。

選んだ形と、その理由

1. テストで短く待つ手段

分と時しか指定できないと、テストが 1 件も流せない。いまのテストは --timeout 1 --retry-count 3 のようにで指定して数秒で終わらせている(client-wait.test.mjs 7 件)。既定値が 8 時間になるため、短く待つ手段が無いと 1 件ごとに待たされる。

内容難点
A(採る) --wait-sec を足す。単位は名前に出ている 指定が 3 通りになる
B 小数を許す(--wait-min 0.05 = 3 秒) 読んで分からない。テストの意図が伝わらない
C 環境変数でテストだけ long-poll を短くする 環境変数が増える。本番と違う経路を通る

案 A に決めた。「単位ごとに 1 つ」という形は --wait-min--wait-hour を持つと決めた時点で既に選ばれている。3 つ目が増えても規則は変わらず、テストが本番と同じ経路を通る。

2. --url--port を同時に指定したとき

エラーにする。--wait-min--wait-hour の扱いと揃う。同じ意味を 2 通りで書けるオプションは、すべて同じ規則にした方が覚えることが減る。

3. 短い形をどれに付けるか

頭文字が衝突する。--room--role はどちらも r--to--timeout はどちらも t。大小で分けると(-r-R)取り違える。

判断
-c--connector-id付ける。毎回打つ
-a--access-token付ける。値が長い
-r--room付ける。--role には付けないjoin でしか使わない)
-p--port付ける
-u--url付ける
-n--nすでにあるrecent の件数)
--to --out --role付けない。衝突するか、打つ回数が少ない
-w--wait-hour付ける。3 つとも w で始まるので、時にだけ割り当てる
--wait-min --wait-sec付けない。-w は時が取った

短い形を全部に付けない。よく打つものだけに付け、残りは長い形だけにする。

-w--wait-hour に割り当てる。時が既定の単位であり、いちばん打つ。分と秒には短い形を付けない。-w が何の単位かを覚え違えると 60 倍・3600 倍ずれるため、迷ったら長い形を書く。

4. --connector-id を省略できるか

内容難点
A(採る) 必須にする。無ければエラーで止める 毎回打つ
B 設計どおり path.basename(process.cwd()) を既定にする 違う場所から叩くと別の名前で参加する。気づきにくい

案 A に決めた。いまの実装も必須になっている(設計とは食い違っているが、動きとしてはこちら)。名乗る名前は取り違えると他プロジェクトの記録に混ざるので、暗黙の既定値を持たせない方が安全である。設計側の記述を実装に合わせて直す。

5. 環境変数を廃止するか

変数いまの用途どうするか
AICHAT_ID名乗る ID廃止(決定済み)
AICHAT_URL接続先廃止する。--url / --port で足りる
AICHAT_PORTサーバー側の待ち受けポート残す。CLI のものではない
AICHAT_DATAサーバー側の置き場残す。同上

CLI 側の環境変数は 2 つとも消え、0 になる。サーバー側の 2 つは役目が違うので触らない。

6. 一覧を 2 か所で保つ方法

オプション名の一覧は 2 か所にある。放っておくとずれる(実際に usage()--retry-countUSAGE--access-token が抜けていた)。

内容難点
A(採る) 別名の表を 1 つ持ち、usage() はそこから組み立てる USAGE の HTML は手で揃えたままになる
B USAGE の表も生成する HTML を機械が書く仕組みが増える。他が手書きなのに 1 か所だけ生成になる
C 両方とも手で揃える いまと同じ。また抜ける

案 A に決めた。短い形を入れるために別名の表はどうせ持つことになる。その表から usage() を組み立てれば、実物とヘルプが食い違うことはなくなる。USAGE は他プロジェクト向けの説明文なので、表だけを機械が書く形にはしない。

テストで守れる。usage() に出る名前が別名の表と一致する」というテストを 1 件書けば、増やしたときに書き忘れても落ちる。

新しいオプション

いまあと備考
$env:AICHAT_ID--connector-id -c必須
$env:AICHAT_URL--url -u接続先をそのまま
--port -plocalhost のポートだけ。--url とは併用できない
--access-token--access-token -a短い形を足すだけ
--room--room -r同上
--timeout消える内部で 240 秒に固定
--retry-count消える回数は内部で計算
--wait-hour既定 8。0 で無限
--wait-min分で指定する
--wait-secテスト・確認用(案 A を採るなら)
--role --to --out -n変えない短い形も付けない

1 行がどうなるか

テスト用サーバーへ繋いで 8 時間待つ場合。

いま(PowerShell 専用・3 行)
  $env:AICHAT_ID = 'ai-chat-lite'
  $env:AICHAT_URL = 'http://localhost:8765'
  node ...\chat.mjs wait --access-token 3f9c1e8a-... --retry-count 120

あと(bash でも PowerShell でも同じ 1 行)
  node ...\chat.mjs wait -c ai-chat-lite -p 8765 -a 3f9c1e8a-...

--wait-hour は書かない。既定が 8 時間になるため、ふだんの待受けでは省ける。

本番で待受けを張る場合はさらに短くなる。

node ...\chat.mjs wait -c ai-chat-lite

段取り

順序

#やること理由
1別名の表で option() を解決する形に変える 土台。これが無いと短い形が入らない。この段では動きを変えない
2--url / --port を足し AICHAT_URL を廃止 接続先が引数になる。テストが叩く経路がここで変わる
3--connector-id を足し AICHAT_ID を廃止 CLI 側の環境変数が 0 になる
4--wait-* を足し --timeout / --retry-count を廃止 いちばん動きが変わる。既定値が 480 秒から 8 時間になる
5usage() を表から組み立て、一致を守るテストを書く ここまでの追加をまとめて反映できる
6資料とルールを直し、他プロジェクトへ周知する 外に出る変更なので最後にまとめる

1 段ずつ、その都度テストを全件通す。2〜4 はどれも既存の呼び出しを壊すため、まとめて変えると原因が分からなくなる。

触るファイル

ファイル何を
src/client/chat.mjs本体。option()usage()cmdWait()BASEUSER_ID
tests/client-wait.test.mjs7 件。--timeout / --retry-count を使っている
tests/server.test.mjsAICHAT_ID を渡している箇所
tools/40_test/テスト用サーバーの起動と後始末
USAGE-FOR-PROJECTS.htmlコマンド × オプションの表と例
notes/90_rules/test-server.html--access-token の例
notes/10_plan/p260829-01-設計.html「無ければ cwd のフォルダ名」を実装に合わせる
~/.claude/CLAUDE.md待受けの例(利用者の指示を待って直す
PlayWright 側ACCESS_TOKEN_ARGS と CLI を叩く箇所

確かめること

やった結果

完了 6 段すべてを通した。テストは 153 件から 176 件になり、全件通過している。

#やったこと結果
1別名の表で解決する形にした option() が短い形も受ける。定義に無い名前を渡すと例外で止まる。recent-n だけ個別に見ていた特別扱いを外した
2--url / --port を足した 既定値を持たない。指定が無ければ繋ぐ直前に止まる。AICHAT_URLAICHAT_PORT はどちらも見ない
3--connector-id を足した AICHAT_ID を廃止。CLI が読む環境変数は 0 になった
4--wait-* に替えた 既定 8 時間・0 で上限なし・2 つ同時はエラー。ログは開始と終了の 2 行だけ。廃止した --timeout / --retry-count はエラーで知らせる
5usage() を表から組み立てた 定義を src/client/options.mjs に分け、テストが同じ表を読んで表示と突き合わせる(15 件)。-h も足した
6資料を直した USAGE-FOR-PROJECTStest-server・この設計。ルールと周知は別に扱う

途中で決めたこと

論点決めたこと
接続先の既定値 持たないことにした。計画では「サーバー側と同じ値を見る」としていたが、既定を本番のポートにするとテストのつもりで叩いたものが本番に入る。実際にそれが起きたため、指定を必須にした
警告を出す条件 自分で長い設定を書いたときだけ。既定が 8 時間になったので、毎回出すと警告の意味がなくなる
定義の置き場 options.mjs に分けた。chat.mjs はトップレベルでコマンドを走らせるため import できず、テストから読めなかった
廃止したオプション 黙って無視せずエラーにした。他プロジェクトの手順に --retry-count 15 が残っており、無視すると待ち時間が効かないまま動く

途中で見つけた不具合

-h を先頭に置くとコマンドとして読まれ、終了コード 1 になっていた。const [, , command, ...rest] の分解で旗が command 側に入り、rest を見ていた判定が拾えなかった。引数の全体を見る WORDS を用意して直した。廃止オプションの検査も同じ穴を持っていたため併せて直っている。

connector への改名との関係

connector への改名は、DB の列名・API のキー・内部の変数名を user_id から connector_id へ変える計画である。この計画とは切り離して進められる。

CLI の名前だけを先に変えてよい。--connector-id で受けた値を内部の USER_ID に渡すだけなので、DB と API はそのまま動く。先に外から見える名前を正しくしておけば、後の改名で他プロジェクトの手順を二度変えずに済む。

ただし whoconnectors のコマンド改名はあちらの計画に残す。API のパスと揃えて変える方が筋が通るためである。