alex fcf7680e49 chore: 自 fox monorepo 移出成獨立公開倉庫(fox #49)
- 自 alterminal/fox 的 cli/ 目錄以 git subtree split 移出(保留 git 歷史)。
- package.json:改為獨立專案(移除 private、補 repository/homepage/files、
  增加 packageManager pnpm@9.15.3)。
- README/docs/cli-install.md:路徑與指令改為本倉庫根目錄版型
  (node dist/cli.js、pnpm build;獨立安裝不會建立 node_modules/.bin/fox,
  掛 PATH 改用 symlink)。
- 新增 .gitignore 與 pnpm-lock.yaml。
- 驗證:pnpm install + pnpm build + node dist/cli.js --help(exit 0)、
  未知命令 exit 2。
2026-09-07 21:14:23 +08:00

Fox CLI — 與 Fox 後端互動的命令列工具

本倉庫已從 alterminal/fox monorepo 的 cli/ 目錄移出成獨立專案(見 alterminal/fox issue #49),改為公開倉庫以開放安裝;git 歷史一併保留。

專案狀態:M0–M3 已實作(M1:HTTP client、設定讀取、tokens verify/auth status;M2:tokens create/list/revoke、公開的 novels get;M3:novels list/create/update、chapters …、generate …)|日期:2026-09-06

fox 是一個命令列工具,讓人與 AI agent 不經過前端,直接與 Fox 後端 API 互動:查詢/建立/編輯作品、管理 access token 等。目標是「一句命令拿到機器可解析的結果」,方便腳本、CI 與 agent 排程使用。

一、設計原則

  1. 非互動優先:所有命令不跳 prompt,參數與環境變數給齊即可執行。缺少必要參數直接報錯(非零 exit code),適合 AI agent 與 cron。
  2. 機器可讀輸出:資料命令預設輸出 JSON(stdout 僅印 JSON,其餘訊息一律走 stderr);人用格式之後再以 --pretty 提供。
  3. 穩定的 exit code:0 成功;1 執行失敗(後端 4xx/5xx、網路錯誤);用法錯誤(缺參數、未知子命令)同樣回非零,訊息在 stderr。
  4. 冪等意識:文件會標明各命令是否幂等(如 tokens revoke 冪等、novels create 會因 slug 重複而失敗),供 agent 重試決策。
  5. Secret 不落檔:token 只從環境變數或本機設定檔讀取(見下),絕不寫進 commit/issue/PR。

二、授權(access token)

後端的 access token(fpat_ 前綴)是 CLI 的主要憑證:

  • 建立:先在 Fox 網頁端以帳號建立,或由管理員以 POST /access-tokens 建立;原始值只在建立時顯示一次。
  • 讀取優先順序:
    1. 環境變數 FOX_API_TOKEN(推薦,適合 agent/CI)
    2. --token <value> 參數(注意:會留在 shell 歷史,僅供本機快速測試)
    3. 本機設定檔 ~/.config/fox/cli.json({"apiUrl": "...", "token": "..."},權限應設 600)
  • 使用方式:每個請求帶 Authorization: Bearer <token>;先用 fox tokens verify 確認有效(過期/撤銷會回 401)。

後端 API 位址由 FOX_API_URL(或設定檔 apiUrl)指定,本機開發預設 http://localhost:3000。

三、命令規劃(對應後端端點)

命令 後端端點 說明
fox auth status GET /auth/status 查詢登入/SSO 設定(公開)
fox tokens verify GET /access-tokens/verify 驗證手中 token 是否有效
fox tokens create --name <名稱> [--expires-at <ISO8601>] [--scopes read,write,generate] POST /access-tokens 建立新 token(回傳只出現一次的原始值)
fox tokens list GET /access-tokens 列出 token(不含 hash/原始值)
fox tokens revoke <id> DELETE /access-tokens/:id 撤銷 token(冪等)
fox novels get <slug> GET /novels/:slug 查單一作品(公開)
fox novels list GET /novels 列出自己的作品(需授權)
fox novels create --title <書名> [--slug <slug>] [--synopsis <簡介>] [--tags <標籤1,標籤2>] POST /novels 建立作品(需授權;標題非拉丁字元時建議附 --slug)
fox novels update <slug> [--title …] [--slug …] [--synopsis …] [--tags …] [--status <狀態>] PATCH /novels/:slug 更新作品(需授權;只傳要改的欄位)
fox chapters list <novelSlug> GET /novels/:novelSlug/chapters 列章節(公開僅 published;帶作者 token 可見全部)
fox chapters get <novelSlug> <chapterSlug> GET /novels/:novelSlug/chapters/:chapterSlug 查單一章節(draft 僅作者/admin)
fox chapters create <novelSlug> --title <標題> [--slug <slug>] [--content <內容|->] [--sort-order <N>] [--status <狀態>] POST /novels/:novelSlug/chapters 建立章節(需授權;狀態預設 draft)
fox chapters update <novelSlug> <chapterSlug> [--title …] [--slug …] [--content …] [--sort-order …] [--status …] PATCH /novels/:novelSlug/chapters/:chapterSlug 更新章節(需授權;只傳要改的欄位)
fox chapters delete <novelSlug> <chapterSlug> DELETE /novels/:novelSlug/chapters/:chapterSlug 刪除章節(需授權;冪等)
fox generate draft <novelSlug> --prompt <指示|-> [--previous-context <前文摘要|->] POST /novels/:novelSlug/generate 草稿生成(需授權;token 需 generate scope)
fox generate continue <novelSlug> --previous-context <前文摘要|-> [--prompt <指示|->] POST /novels/:novelSlug/generate/continue 續寫(前文摘要必填)
fox generate rewrite <novelSlug> --prompt <原文|-> [--previous-context …] POST /novels/:novelSlug/generate/rewrite 改寫(原文放在 --prompt)
fox generate usages <novelSlug> GET /novels/:novelSlug/generate/usages 查詢生成用量記帳(需授權)

授權:受保護端點的 AuthGuard 同時接受 Authorization: Bearer <access token> 與瀏覽器 session(Bearer 優先)。access token 需綁定帳號(POST /access-tokens 帶 accountId,或由管理員建立時指定),未綁帳號的系統 token 只能用於 tokens verify。生成命令需具備 generate scope(建立 token 時 --scopes read,write,generate;缺 scope 回 403)。

多行內容:--content/--prompt/--previous-context 的值為 - 時改從 stdin 讀入全部內容,適合管線傳入多行文字:cat 章節.md | fox chapters create <novelSlug> --title <標題> --content -。

四、AI agent 使用指引

  • 每個命令都有 --help;未知命令回非零 exit code。
  • 輸出為單一 JSON 物件,可直接 jq 解析;錯誤時 stderr 有人類可讀訊息,stdout 不印半成品。
  • agent 拿到 token 的建議流程:由人透過加密渠道交付(組織公開金鑰加密,見 alterminal/agents 的 AGENTS.md 2.3),存入環境變數或設定檔,不寫入任何儲存庫內容。

五、技術棧與開發計畫

  • 實作語言:Node.js(≥22)+ TypeScript,與 frontend/backend 同語言。
  • 獨立倉庫:本專案位於 alterminal/fox-cli(自 alterminal/fox 移出,issue #49),不屬於 fox monorepo workspace;以 pnpm 於本倉庫根目錄安裝與建置。

里程碑:

  • M0:子項目目錄+README(完成)。
  • M1:HTTP client、設定讀取、tokens verify/auth status(完成,見 src/http.ts、src/config.ts)。
  • M2:tokens create/list/revoke、公開的 novels get(完成)。
  • M3:novels list/create/update、chapters list/get/create/update/delete、generate draft/continue/rewrite/usages(完成,2026-09-06,issue #43)。

開發

使用者安裝與設定說明見 docs/cli-install.md。

git clone https://gitea.alterminal.com/alterminal/fox-cli.git
cd fox-cli
pnpm install
pnpm build
node dist/cli.js <子命令>   # 例如 auth status

結構:src/cli.ts(進入點與分發)、src/command.ts(參數解析與註冊表)、 src/config.ts(設定讀取)、src/http.ts(fetch 封裝)、src/commands.ts(各命令實作)、 src/errors.ts(錯誤與 exit code)。

exit code:0 成功;1 執行失敗(後端 4xx/5xx、網路錯誤);2 用法錯誤。 tokens revoke 成功時輸出 {"ok": true, "id": <id>}(後端回 204 無內容)。

維護說明

  1. 後端端點異動時,同步更新第三節對應表。
  2. 命令列介面(參數、輸出欄位)保持向下相容;破壞性變更須在 README 註明版本。
S
Description
Fox CLI 客戶端:與 Fox 後端 API 互動的命令列工具(供人與 AI agent 使用)
Readme
72 KiB
Languages
TypeScript 79.5%
JavaScript 20.5%