Files
bear-cli/docs/commands.md
T
alex 14edb84a59 docs: 新增 bear CLI 指令規劃(issue #19)
- 建立獨立倉庫 bear-cli,用於實現 bear 的終端機 CLI 客戶端
- README.md:專案簡介、指令總覽、全域選項、憑證與里程碑
- docs/commands.md:完整指令規格(login/whoami/token/logout/status/apps)
  - 沿用 RFC 8628 Device Authorization Grant 方向(見 bear issue #17 設計文件)
  - 定義全域選項、各指令行為、退出碼、設定/憑證檔與安全考量
- 依需求「先規劃指令、暫不實作」,程式碼留待 P2 起各自開 issue 再進行
2026-08-29 17:25:53 +08:00

7.1 KiB
Raw Blame History

Bear CLI 指令規劃(Command Spec)

狀態:規劃草案(對應 issue #19「創建 bear cli 倉庫」) 範圍:本文件只規劃指令介面,不實作程式碼。 登入採用的 OIDC Device Authorization Grant(RFC 8628)細節,見 bear 倉庫 docs/cli-feature-plan.md(issue #17)。


1. 命名與呼叫慣例

  • 可執行檔名:bear(Linux 終端機呼叫 bear <command>)。
  • 指令採「動詞在前」的扁平結構,不設多層子指令(首版維持簡單,後續需要再擴充)。
  • 全部指令支援 --json 輸出機器可讀結果;人類可讀輸出為預設。
  • 輸出語言跟隨系統 Locale,優先繁體中文(zh_TW),英文(en)為後備。

2. 全域選項(Global Options)

選項 型別 預設 說明
--issuer URL string https://alterminal.com Bear(OIDC Provider)位址;可被設定檔覆寫
--config PATH string ~/.config/bear/config.json 設定檔路徑
--json bool false 機器可讀輸出(JSON)
-v, --verbose bool false 顯示詳細日誌(含 HTTP 請求摘要,但不含 token)
-h, --help bool — 顯示說明
--version bool — 顯示版本後離開

優先序:CLI flag > 環境變數(BEAR_ISSUER)> 設定檔 > 內建預設。


3. 指令詳述

3.1 bear login

啟動 Device Flow 登入,取得並保存 Token。

bear login [--scope "openid profile email"] [--client-id ID]
選項 預設 說明
--scope openid profile email 請求的 scope(空白分隔)
--client-id 設定檔內值 OIDC client id

行為:

  1. 讀取設定 → 向 {issuer}/.well-known/openid-configuration 取 device_authorization_endpoint(動態發現,不寫死網址)。

  2. POST /device_authorization(client_id + scope)。

  3. 終端印出:

    請在瀏覽器開啟:https://alterminal.com/device
    輸入代碼:ABCD-EFGH
    

    若終端支援,同步印出 QR(掃碼直達 verification_uri_complete)。

  4. 以 interval 週期輪詢 POST /token(grant_type=device_code):

    • authorization_pending → 繼續等待;
    • slow_down → 加大輪詢間隔;
    • access_denied → 中止並提示;
    • 成功 → 寫入憑證檔(0600),印出 已登入:<email>。

退出碼:0 成功;4 等待逾時(expires_in);5 使用者拒絕;6 網路/伺服器錯誤。

--json 輸出範例(成功):

{"ok": true, "email": "alice@example.com", "expires_in": 3600}

3.2 bear whoami

顯示目前登入身分(GET /userinfo,Bearer access token)。

bear whoami

行為:讀取快取的 access token(過期則先用 refresh token 輪轉換新),呼叫 /userinfo,印出 claims(name、email、picture 等)。

退出碼:0 成功;3 未登入。

輸出範例:

sub        : 0190...uuid
name       : Alice Chen
email      : alice@example.com
picture    : https://...

3.3 bear token [--refresh]

印出 access token 到 stdout,供 pipe 給其他工具(如 curl、腳本)。

bear token [--refresh]
選項 說明
--refresh 強制先以 refresh token 輪轉換新 access token

行為:

  • 若無 --refresh 且快取的 access token 未過期 → 直接印出。
  • 若過期(或指定 --refresh)→ 以 refresh token 向 /token 換新,更新快取後印出。
  • 輸出只含 token 本體(單行、無前綴),方便 pipe;診斷訊息一律走 stderr。

退出碼:0 成功;3 未登入;1 refresh 失敗(token 已撤銷或過期,需重新 login)。


3.4 bear logout

撤銷 refresh token 並清除本機憑證。

bear logout

行為:呼叫 POST /revoke(撤銷 refresh token),無論伺服器回應如何,皆刪除本機憑證檔。

退出碼:0 成功;6 伺服器呼叫失敗(但本機憑證已清除)。


3.5 bear status

顯示登入狀態與 token 剩餘效期(不呼叫網路,純本機判定)。

bear status

行為:讀取本機憑證,印出登入與否、access token 剩餘秒數、refresh token 是否存在。

退出碼:0 已登入;3 未登入。

輸出範例:

已登入:alice@example.com
access token 剩餘:3210 秒
refresh token:有
issuer:https://alterminal.com

3.6 bear apps(P3,暫緩)

列出「公開應用」清單,供 Launch/跳轉參考。

bear apps

前置:bear 伺服器端需新增「公開應用清單」API(列為 P3,待確認)。

退出碼:0 成功;3 未登入;6 API 尚未提供。


4. 退出碼總表

碼 語意
0 成功
1 一般錯誤(含 refresh 失敗、憑證檔讀寫失敗)
2 用法錯誤(未知指令/參數)
3 未登入(需先 bear login)
4 授權等待逾時(authorization_pending 超過 expires_in)
5 授權被拒絕(access_denied)
6 網路/伺服器錯誤
7 設定檔/憑證檔格式損毀

5. 設定檔與憑證檔

檔 路徑 內容 權限
設定 ~/.config/bear/config.json issuer、client_id、scope 0644
憑證 ~/.local/state/bear/credentials.json refresh_token(優先)+快取 access_token/expires_at 0600
  • 只以 refresh token 為主:access token 短命快取,過期以 refresh token 輪轉換新(沿用 Bear 既有 refresh rotation + 重用偵測)。
  • 寫入憑證檔務必 0600,且以 O_CREAT|O_EXCL 防止 symlink 攻擊。
  • 未來可擴充系統 keyring(libsecret / Keychain),避免明文檔。

6. 錯誤處理與安全

  • authorization_pending、slow_down、access_denied、invalid_grant 依 RFC 8628 §3.5 顯示對應中文提示。
  • 所有診斷訊息走 stderr;--json 模式將錯誤以 {"ok": false, "error": "...", "code": N} 輸出。
  • token、user_code、device_code 一律不入 log、不入 stdout(除 bear token 之目的外)、不入版本庫。
  • 網路層一律使用 Req,遵循 bear 倉庫 HTTP 客戶端慣例。

7. 開放問題(待確認)

  1. CLI 的 OIDC client 採新 method: "device"(client auth 為 none)或沿用 PKCE+JWK?傾向前者(見 bear cli-feature-plan.md §5.5)。
  2. 發行格式:escript(目標機需 Erlang)或 self-contained release(bakeware/burrito)?
  3. bear apps 所需的「公開應用清單」API 是否納入 P3?
  4. 是否支援 offline_access scope,或沿用現行 refresh 輪轉即可?

8. 對應關係

本指令 對應 OIDC/Bear 端點
login /.well-known/openid-configuration → POST /device_authorization → POST /token(device_code)
whoami GET /userinfo
token --refresh POST /token(refresh_token)
logout POST /revoke
apps(P3) 待新增「公開應用清單」API