@recur-tw/cli 0.1.0 → 0.1.1

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.
Files changed (3) hide show
  1. package/README.md +82 -22
  2. package/dist/cli.mjs +4 -4
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -21,7 +21,7 @@ npx @recur-tw/cli products list
21
21
  前往 [Recur Dashboard](https://app.recur.tw) 取得 Secret Key(`sk_test_*` 或 `sk_live_*`),然後執行:
22
22
 
23
23
  ```bash
24
- recur --key sk_test_xxx login
24
+ recur login
25
25
  ```
26
26
 
27
27
  API Key 會安全存儲在 `~/.recur/credentials.json`(檔案權限 `0600`)。
@@ -58,7 +58,7 @@ recur <資源> <動作> [選項]
58
58
  | `--key <sk_*>` | 指定 API Secret Key |
59
59
  | `--profile <name>` | 使用指定的 profile |
60
60
  | `--base-url <url>` | API 位址覆寫 |
61
- | `--output <format>` | 輸出格式:`json`、`table`(預設)、`csv` |
61
+ | `--output <format>` | 輸出格式:`json`、`table`(預設)、`csv`、`ndjson` |
62
62
  | `--fields <fields>` | 逗號分隔的欄位篩選 |
63
63
  | `--dry-run` | 僅本地驗證,不發送 API 請求 |
64
64
  | `--json <payload>` | 直接傳入 JSON 作為 API request body |
@@ -66,9 +66,8 @@ recur <資源> <動作> [選項]
66
66
  ### 驗證管理
67
67
 
68
68
  ```bash
69
- recur login # 互動式設定 API Key
70
- recur --key sk_test_xxx login # 直接設定
71
- recur whoami # 顯示目前 profile
69
+ recur login # 互動式設定 API Key(輸入時遮蔽顯示)
70
+ recur whoami # 顯示目前 profile 與 masked key
72
71
  recur profiles # 列出所有 profile
73
72
  recur use <profile> # 切換 profile
74
73
  recur logout [profile] # 移除 profile
@@ -95,7 +94,7 @@ recur --profile sandbox products list
95
94
 
96
95
  ```bash
97
96
  recur products list # 列出所有產品
98
- recur products list --status active # 篩選狀態
97
+ recur products list --status archived # 列出已封存產品
99
98
  recur products get <id> # 以 ID 查詢
100
99
  recur products get <slug> # 以 slug 查詢
101
100
  recur products create --name "方案" --price 299 --interval monthly --type SUBSCRIPTION
@@ -109,7 +108,8 @@ recur products archive <id>
109
108
  ```bash
110
109
  recur customers list # 列出所有客戶
111
110
  recur customers list --email user@example.com # 以 email 篩選
112
- recur customers list --limit 50 --offset 100 # 分頁
111
+ recur customers list --starting-after <id> --limit 50 # 游標分頁
112
+ recur customers list --page-all # 自動分頁(輸出 NDJSON)
113
113
  recur customers get <id> # 查詢客戶詳情
114
114
  recur customers update <id> --name "新名稱"
115
115
  ```
@@ -119,8 +119,8 @@ recur customers update <id> --name "新名稱"
119
119
  ```bash
120
120
  recur subscriptions list # 列出所有訂閱
121
121
  recur subscriptions list --status active # 篩選狀態
122
- recur subscriptions list --customer-id cus_xxx # 以客戶篩選
123
- recur subscriptions list --email user@example.com # 以 email 篩選
122
+ recur subscriptions list --customer-id <id> # 以客戶篩選
123
+ recur subscriptions list --page-all # 自動分頁
124
124
  recur subscriptions get <id> # 查詢訂閱詳情
125
125
  recur subscriptions cancel <id> # 期末取消
126
126
  recur subscriptions cancel <id> --immediately # 立即取消
@@ -131,7 +131,7 @@ recur subscriptions cancel <id> --immediately # 立即取消
131
131
  ```bash
132
132
  recur orders list # 列出所有訂單
133
133
  recur orders list --status paid # 篩選狀態
134
- recur orders list --customer-id cus_xxx # 以客戶篩選
134
+ recur orders list --customer-id <id> # 以客戶篩選
135
135
  recur orders get <id> # 查詢訂單詳情
136
136
  ```
137
137
 
@@ -139,8 +139,8 @@ recur orders get <id> # 查詢訂單詳情
139
139
 
140
140
  ```bash
141
141
  recur invoices list # 列出所有帳單
142
- recur invoices list --subscription-id sub_xxx # 以訂閱篩選
143
- recur invoices list --customer-id cus_xxx # 以客戶篩選
142
+ recur invoices list --subscription-id <id> # 以訂閱篩選
143
+ recur invoices list --customer-id <id> # 以客戶篩選
144
144
  recur invoices list --status paid # 篩選狀態
145
145
  recur invoices get <id> # 查詢帳單詳情
146
146
  ```
@@ -159,7 +159,7 @@ recur webhooks listen http://localhost:3000/api/webhooks # 即時轉發到本
159
159
 
160
160
  ### 本地 Webhook 開發(`webhooks listen`)
161
161
 
162
- 類似 `stripe listen`,`recur webhooks listen` 讓你在本地開發時即時接收 webhook 事件,不需要公開 URL。
162
+ `recur webhooks listen` 讓你在本地開發時即時接收 webhook 事件,不需要公開 URL。
163
163
 
164
164
  ```bash
165
165
  # 基本用法:轉發所有事件到本地伺服器
@@ -211,8 +211,8 @@ recur webhooks listen http://localhost:3000/api/webhooks --events checkout.compl
211
211
  ### Checkout Sessions
212
212
 
213
213
  ```bash
214
- recur checkouts create --product-id prod_xxx --customer-email user@example.com
215
- recur checkouts create --json '{"productId":"prod_xxx","successUrl":"https://..."}'
214
+ recur checkouts create --product-id <id> --customer-email user@example.com
215
+ recur checkouts create --json '{"productId":"<id>","successUrl":"https://..."}'
216
216
  recur checkouts get <id> # 查詢 session 狀態
217
217
  ```
218
218
 
@@ -237,7 +237,7 @@ name price type
237
237
  $ recur products list --output json
238
238
 
239
239
  [
240
- { "id": "prod_xxx", "name": "大師方案", "price": 799 },
240
+ { "id": "k672i1kd6zgrw5b6w39xwpx3", "name": "大師方案", "price": 799 },
241
241
  ...
242
242
  ]
243
243
  ```
@@ -249,6 +249,13 @@ recur products list --output json | jq '.[].name'
249
249
  recur subscriptions list --output json | jq '[.[] | select(.status == "ACTIVE")]'
250
250
  ```
251
251
 
252
+ ### NDJSON(適合串流處理)
253
+
254
+ ```bash
255
+ # --page-all 自動輸出 NDJSON(一行一筆)
256
+ recur customers list --page-all --fields id,email
257
+ ```
258
+
252
259
  ### CSV(適合匯出與試算表)
253
260
 
254
261
  ```bash
@@ -264,7 +271,58 @@ recur products list --fields id,name,price
264
271
  recur customers list --fields email,name --output json
265
272
  ```
266
273
 
267
- ## AI Agent 整合
274
+ ## MCP Server(AI Agent 整合)
275
+
276
+ `recur mcp` 啟動一個本地 MCP(Model Context Protocol)server,讓 AI 助理直接操作 Recur API。
277
+
278
+ ### Claude Desktop
279
+
280
+ 在 `claude_desktop_config.json` 中加入:
281
+
282
+ ```json
283
+ {
284
+ "mcpServers": {
285
+ "recur": {
286
+ "command": "npx",
287
+ "args": ["@recur-tw/cli", "mcp"],
288
+ "env": { "RECUR_SECRET_KEY": "sk_test_xxx" }
289
+ }
290
+ }
291
+ }
292
+ ```
293
+
294
+ ### Claude Code
295
+
296
+ 在專案根目錄的 `.mcp.json` 中加入:
297
+
298
+ ```json
299
+ {
300
+ "mcpServers": {
301
+ "recur": {
302
+ "command": "npx",
303
+ "args": ["@recur-tw/cli", "mcp"],
304
+ "env": { "RECUR_SECRET_KEY": "sk_test_xxx" }
305
+ }
306
+ }
307
+ }
308
+ ```
309
+
310
+ ### 提供的 Tools(22 個)
311
+
312
+ | 類別 | Tools | 類型 |
313
+ |------|-------|------|
314
+ | Schema | `get_schema` | 唯讀 |
315
+ | Products | `list_products`, `get_product`, `create_product`, `update_product`, `archive_product` | 讀寫 |
316
+ | Customers | `list_customers`, `get_customer`, `update_customer` | 讀寫 |
317
+ | Subscriptions | `list_subscriptions`, `get_subscription`, `cancel_subscription` | 讀寫 |
318
+ | Orders | `list_orders`, `get_order` | 唯讀 |
319
+ | Invoices | `list_invoices`, `get_invoice` | 唯讀 |
320
+ | Webhooks | `list_webhooks`, `create_webhook`, `test_webhook`, `delete_webhook` | 讀寫 |
321
+ | Checkouts | `create_checkout`, `get_checkout` | 寫入 |
322
+
323
+ 所有 tools 帶有 MCP Tool Annotations(`readOnlyHint`、`destructiveHint`),讓 agent 能判斷操作風險。
324
+
325
+ ## Agent-Optimized 設計
268
326
 
269
327
  此 CLI 遵循 [Agent-Optimized CLI](https://justin.poehnelt.com/posts/rewrite-your-cli-for-ai-agents/) 設計原則:
270
328
 
@@ -305,12 +363,12 @@ recur products create --dry-run --json '{"name":"Test","price":299}'
305
363
 
306
364
  ### Input 驗證(防止 AI 幻覺)
307
365
 
308
- CLI 內建多層輸入驗證,防止 Agent 送出錯誤的 ID 或惡意輸入:
366
+ CLI 內建多層輸入驗證,防止 Agent 送出錯誤或惡意輸入:
309
367
 
310
- - Resource ID 前綴驗證(`prod_*`、`cus_*`、`sub_*` 等)
311
368
  - 路徑穿越偵測(`../`、`/`、`\`)
312
- - 特殊字元阻擋(`?`、`#`、`%`)
313
- - 控制字元過濾
369
+ - Query injection 阻擋(`?`、`#`、`%`)
370
+ - 控制字元與不可見 Unicode 過濾
371
+ - API 回應 sanitization(ANSI escape、零寬字元)
314
372
 
315
373
  ## 驗證方式
316
374
 
@@ -331,10 +389,12 @@ CLI 僅接受 Secret Key。Publishable Key(`pk_*`)僅供前端 SDK 使用。
331
389
 
332
390
  ### 安全性
333
391
 
392
+ - Login 輸入 key 時以 `*` 遮蔽顯示
334
393
  - API Key 以 `0600` 權限存儲在 `~/.recur/credentials.json`
335
394
  - CLI 不直接連接資料庫,所有操作經由 API server 驗證
336
395
  - 每個 API Key 綁定一個 Organization,資料完全隔離
337
396
  - Key 以 SHA-256 hash 存儲在 server 端
397
+ - API 回應自動 sanitize 以防止 prompt injection
338
398
 
339
399
  ## 程式化使用
340
400
 
@@ -353,7 +413,7 @@ const products = await client.get('/v1/products')
353
413
 
354
414
  ## 系統需求
355
415
 
356
- - Node.js >= 18
416
+ - Node.js >= 22
357
417
  - 作業系統:macOS、Linux、Windows
358
418
 
359
419
  ## 授權
package/dist/cli.mjs CHANGED
@@ -920,7 +920,7 @@ var RecurClient = class {
920
920
  }
921
921
  const headers = {
922
922
  Authorization: `Bearer ${this.secretKey}`,
923
- "User-Agent": `@recur-tw/cli/0.1.0`
923
+ "User-Agent": `@recur-tw/cli/0.1.1`
924
924
  };
925
925
  const hasBody = opts?.body !== void 0;
926
926
  if (hasBody) headers["Content-Type"] = "application/json";
@@ -1676,7 +1676,7 @@ async function parseSSEStream(body, handlers, signal) {
1676
1676
  }
1677
1677
  }
1678
1678
  function registerListenSubcommand(webhooksCmd) {
1679
- const listenCmd = webhooksCmd.command("listen").description("Forward webhook events from Recur to your local server in real-time (similar to stripe listen)").argument("<url>", "Local URL to forward events to (e.g. http://localhost:3000/api/webhooks)").option("--events <types>", "Comma-separated event types to filter (e.g. checkout.completed,order.paid)").option("--relay-url <url>", "Override relay server URL (for development)");
1679
+ const listenCmd = webhooksCmd.command("listen").description("Forward webhook events from Recur to your local server in real-time").argument("<url>", "Local URL to forward events to (e.g. http://localhost:3000/api/webhooks)").option("--events <types>", "Comma-separated event types to filter (e.g. checkout.completed,order.paid)").option("--relay-url <url>", "Override relay server URL (for development)");
1680
1680
  listenCmd.addHelpText("after", `
1681
1681
  Connects to Recur's SSE relay and forwards webhook events to your local server.
1682
1682
  Each session gets a unique signing secret (whsec_*) for verifying event signatures.
@@ -2489,7 +2489,7 @@ Requires a Secret Key (sk_test_* or sk_live_*) via --key, RECUR_SECRET_KEY, or r
2489
2489
  });
2490
2490
  const server = new McpServer({
2491
2491
  name: "recur",
2492
- version: "0.1.0"
2492
+ version: "0.1.1"
2493
2493
  }, { capabilities: { tools: {} } });
2494
2494
  registerTools(server, client);
2495
2495
  const transport = new StdioServerTransport();
@@ -2505,7 +2505,7 @@ Requires a Secret Key (sk_test_* or sk_live_*) via --key, RECUR_SECRET_KEY, or r
2505
2505
  //#endregion
2506
2506
  //#region src/cli.ts
2507
2507
  const program = new Command();
2508
- program.name("recur").description("Recur CLI — Taiwan subscription payment platform.\nManage products, customers, subscriptions, webhooks, and more.\nAll commands require a Secret Key (sk_test_* or sk_live_*).").version("0.1.0").option("--key <secret-key>", "API secret key (sk_test_* or sk_live_*)").option("--profile <name>", "Use a named profile from ~/.recur/credentials.json").option("--base-url <url>", "API base URL (default: https://api.recur.tw)").option("--output <format>", "Output format: json, table, csv, ndjson (default: json when piped, table otherwise)").hook("preAction", (thisCommand) => {
2508
+ program.name("recur").description("Recur CLI — Taiwan subscription payment platform.\nManage products, customers, subscriptions, webhooks, and more.\nAll commands require a Secret Key (sk_test_* or sk_live_*).").version("0.1.1").option("--key <secret-key>", "API secret key (sk_test_* or sk_live_*)").option("--profile <name>", "Use a named profile from ~/.recur/credentials.json").option("--base-url <url>", "API base URL (default: https://api.recur.tw)").option("--output <format>", "Output format: json, table, csv, ndjson (default: json when piped, table otherwise)").hook("preAction", (thisCommand) => {
2509
2509
  const opts = thisCommand.opts();
2510
2510
  if (!opts.output) opts.output = process.stdout.isTTY ? "table" : "json";
2511
2511
  if (![
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@recur-tw/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "CLI for Recur - Taiwan's subscription payment platform",
5
5
  "keywords": [
6
6
  "recur",