team-toon-tack 1.7.0 → 2.0.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.
package/README.zh-TW.md CHANGED
@@ -2,405 +2,73 @@
2
2
 
3
3
  繁體中文 | [English](./README.md)
4
4
 
5
- 使用 TOON 格式同步與管理 Linear 任務的 CLI 工具。
5
+ Claude Code 最佳化的 Linear 工作流 比 MCP 節省大量 token。
6
6
 
7
- ## 為什麼需要這個工具?
7
+ ## 特色功能
8
8
 
9
- 在使用 Linear 管理專案任務時,常見的痛點:
9
+ - **節省 Token** — 本地 cycle 快取避免重複 API 呼叫,比 Linear MCP 省下大量 token
10
+ - **智慧任務挑選** — `/work-on next` 自動選擇最高優先級的未指派工作
11
+ - **多團隊支援** — 跨多個團隊同步與過濾 issue
12
+ - **彈性同步模式** — 選擇 remote(即時同步 Linear)或 local(離線優先,稍後用 `--update` 同步)
13
+ - **QA/PM 團隊支援** — 完成開發任務時自動將 QA/PM 團隊的 parent issue 更新為「Testing」
14
+ - **附件下載** — 自動下載 Linear 圖片和檔案到本地 `.ttt/output/`,供 AI 視覺分析
15
+ - **阻塞狀態** — 等待外部依賴時可設定任務為 blocked
16
+ - **自動安裝指令** — `ttt init` 可自動安裝 Claude Code commands,支援自訂前綴
17
+ - **Cycle 歷史保存** — 本地 `.toon` 檔案保留 cycle 資料,方便 AI 檢閱
18
+ - **使用者過濾** — 只顯示指派給你或未指派的工作
10
19
 
11
- - **AI 助手整合困難**:Claude Code 等 AI 工具無法直接讀取 Linear 的任務上下文
12
- - **狀態同步繁瑣**:手動在 Linear 和本地之間切換更新狀態
13
- - **團隊協作不透明**:難以追蹤誰在做什麼、進度如何
14
-
15
- **team-toon-tack** 解決這些問題:將 Linear 任務同步到本地 TOON 檔案,讓 AI 助手能讀取任務內容,並自動同步狀態變更。
16
-
17
- ## 運作原理
18
-
19
- ```
20
- ┌─────────────┐ ┌──────────────┐ ┌─────────────┐
21
- │ Linear │────▶│ ttt sync │────▶│ cycle.toon │
22
- │ (雲端) │ │ │ │ (本地) │
23
- └─────────────┘ └──────────────┘ └─────────────┘
24
-
25
-
26
- ┌─────────────┐ ┌──────────────┐ ┌─────────────┐
27
- │ Linear │◀────│ ttt done │◀────│ Claude Code │
28
- │ 狀態更新 │ │ ttt work-on │ │ 讀取任務 │
29
- └─────────────┘ └──────────────┘ └─────────────┘
30
- ```
31
-
32
- ### 核心流程
33
-
34
- 1. **同步 (sync)**
35
- - 從 Linear API 抓取當前 Cycle 的任務
36
- - 根據 `local.ttt` 設定過濾(標籤、排除指派人)
37
- - 寫入 `cycle.toon`,包含完整任務資訊
38
-
39
- 2. **開始任務 (work-on)**
40
- - 讀取 `cycle.toon` 中的待處理任務
41
- - 更新本地狀態為 `in-progress`
42
- - 同步更新 Linear 狀態為 "In Progress"
43
-
44
- 3. **完成任務 (done)**
45
- - 更新本地狀態為 `completed`
46
- - 同步更新 Linear 狀態為 "Done"
47
- - 自動在 Linear 新增完成留言(含 commit 資訊)
48
- - 若有父任務,自動更新為 "Testing"
49
-
50
- ### 檔案結構與用途
51
-
52
- ```
53
- .ttt/ # 配置目錄(建議 gitignore)
54
- ├── config.toon # 團隊配置
55
- │ ├── teams # Linear 團隊 ID 映射
56
- │ ├── users # 成員 ID/email 映射
57
- │ ├── labels # 標籤 ID 映射
58
- │ ├── status_transitions # 狀態映射配置
59
- │ └── current_cycle # 當前 Cycle 資訊
60
-
61
- ├── local.toon # 個人設定(必須 gitignore)
62
- │ ├── current_user # 你的 user key
63
- │ ├── team # 主要團隊
64
- │ ├── teams # 多團隊同步(可選)
65
- │ ├── label # 過濾標籤(可選)
66
- │ ├── exclude_labels # 排除的標籤
67
- │ └── exclude_assignees # 排除的指派人
68
-
69
- └── cycle.toon # 任務資料(自動產生)
70
- ├── cycleId # Cycle UUID
71
- ├── cycleName # Cycle 名稱
72
- ├── updatedAt # 最後同步時間
73
- └── tasks[] # 任務列表
74
- ├── id # 任務編號 (MP-123)
75
- ├── linearId # Linear UUID
76
- ├── title # 標題
77
- ├── description # 描述(Markdown)
78
- ├── status # Linear 狀態
79
- ├── localStatus # 本地狀態
80
- ├── priority # 優先級 (1=Urgent, 4=Low)
81
- ├── labels # 標籤列表
82
- ├── branch # Git 分支名
83
- ├── attachments # 附件列表
84
- └── comments # 留言列表
85
- ```
20
+ ## 快速開始
86
21
 
87
- ## 安裝
22
+ ### 1. 安裝與初始化
88
23
 
89
24
  ```bash
90
- # npm(推薦)
91
25
  npm install -g team-toon-tack
92
-
93
- # 或用 bun
94
- bun add -g team-toon-tack
95
- ```
96
-
97
- ## 快速開始
98
-
99
- ```bash
100
- # 1. 設定 Linear API 金鑰
101
26
  export LINEAR_API_KEY="lin_api_xxxxx"
102
27
 
103
- # 2. 初始化(會從 Linear 抓取團隊資料)
104
- mkdir .ttt && cd .ttt
28
+ cd your-project
105
29
  ttt init
106
-
107
- # 3. 同步任務
108
- ttt sync
109
-
110
- # 4. 開始工作
111
- ttt work-on
112
30
  ```
113
31
 
114
- ## 使用情境
115
-
116
- ### 情境 1:每日開工流程
117
-
118
- ```bash
119
- # 早上開始工作前,同步最新任務
120
- ttt sync -d .ttt
121
-
122
- # 查看待處理任務並選擇一個開始
123
- ttt work-on -d .ttt
124
-
125
- # Claude Code 現在可以讀取任務內容
126
- # 在 .ttt/cycle.toon 中找到任務描述、附件等
127
- ```
128
-
129
- ### 情境 2:搭配 Claude Code 自動化
130
-
131
- 建立以下三個 slash command 檔案:
32
+ 初始化時會設定:
33
+ - **狀態來源**:`remote`(即時更新 Linear)或 `local`(離線工作,用 `ttt sync --update` 同步)
34
+ - **QA/PM 團隊**:跨團隊 parent issue 更新(需在 Linear 設定 parent)
35
+ - **Claude Code commands**:自動安裝,可選前綴(如 `/ttt:work-on`)
132
36
 
133
- #### `.claude/commands/sync-linear.md`
37
+ ### 2. 每日工作流
134
38
 
135
- ```markdown
136
- ---
137
- name: sync-linear
138
- description: Sync Linear issues to local TOON file
139
- ---
140
-
141
- # Sync Linear Issues
142
-
143
- Fetch current cycle's issues from Linear to `.ttt/cycle.toon`.
144
-
145
- ## Process
146
-
147
- ### 1. Run Sync
148
-
149
- \`\`\`bash
150
- ttt sync -d .ttt
151
- \`\`\`
152
-
153
- ### 2. Review Output
39
+ 在 Claude Code 中:
154
40
 
155
- Script displays a summary of tasks in the current cycle.
156
-
157
- ## When to Use
158
-
159
- - Before starting a new work session
160
- - When task list is missing or outdated
161
- - After issues are updated in Linear
162
41
  ```
163
-
164
- #### `.claude/commands/work-on.md`
165
-
166
- ```markdown
167
- ---
168
- name: work-on
169
- description: Select and start working on a Linear issue
170
- arguments:
171
- - name: issue-id
172
- description: "Issue ID (e.g., MP-624) or 'next' for auto-select"
173
- required: false
174
- ---
175
-
176
- # Start Working on Issue
177
-
178
- Select a task and update status to "In Progress" on both local and Linear.
179
-
180
- ## Process
181
-
182
- ### 1. Run Command
183
-
184
- \`\`\`bash
185
- ttt work-on -d .ttt $ARGUMENTS
186
- \`\`\`
187
-
188
- ### 2. Review Issue Details
189
-
190
- Script displays title, description, priority, labels, and attachments.
191
-
192
- ### 3. Implement
193
-
194
- 1. Read the issue description carefully
195
- 2. Explore related code
196
- 3. Implement the fix/feature
197
- 4. Run validation commands
198
- 5. Commit with conventional format
199
- 6. Use `/done-job` to complete
42
+ /sync # 從 Linear 取得當前 cycle 所有 issue
43
+ /work-on next # 挑選最高優先級任務並開始工作
44
+ /done-job # 完成任務,附上 AI 生成的摘要
200
45
  ```
201
46
 
202
- #### `.claude/commands/done-job.md`
47
+ 就這樣。
203
48
 
204
- ```markdown
205
49
  ---
206
- name: done-job
207
- description: Mark a Linear issue as done with AI summary comment
208
- arguments:
209
- - name: issue-id
210
- description: Linear issue ID (e.g., MP-624). Optional if only one task is in-progress
211
- required: false
212
- ---
213
-
214
- # Complete Task
215
-
216
- Mark a task as done and update Linear with commit details.
217
-
218
- ## Process
219
-
220
- ### 1. Determine Issue ID
221
-
222
- Check `.ttt/cycle.toon` for tasks with `localStatus: in-progress`.
223
-
224
- ### 2. Write Fix Summary
225
50
 
226
- Prepare a concise summary (1-3 sentences) covering:
227
- - Root cause
228
- - How it was resolved
229
- - Key code changes
230
-
231
- ### 3. Run Command
232
-
233
- \`\`\`bash
234
- ttt done -d .ttt $ARGUMENTS -m "修復說明"
235
- \`\`\`
236
-
237
- ## What It Does
238
-
239
- - Linear issue status → "Done"
240
- - Adds comment with commit hash, message, and diff summary
241
- - Parent issue (if exists) → "Testing"
242
- - Local status → `completed` in `.ttt/cycle.toon`
243
- ```
244
-
245
- #### 使用方式
246
-
247
- ```
248
- /sync-linear # 同步任務
249
- /work-on # 互動選擇任務
250
- /work-on MP-624 # 指定任務
251
- /work-on next # 自動選最高優先級
252
- /done-job # 完成當前任務
253
- /done-job MP-624 # 完成指定任務
254
- ```
255
-
256
- Claude Code 會自動:
257
- - 執行 `ttt work-on` 開始任務
258
- - 讀取任務描述和附件
259
- - 根據需求實作功能
260
- - 執行 `ttt done` 更新狀態並留言
261
-
262
- ### 情境 3:完成任務並自動留言
263
-
264
- ```bash
265
- # 完成開發後
266
- git add . && git commit -m "feat: implement feature X"
267
-
268
- # 標記任務完成,會自動在 Linear 新增留言
269
- ttt done -d .ttt -m "實作了 X 功能,修改了 Y 元件"
270
- ```
271
-
272
- Linear 上會自動新增留言:
273
- ```markdown
274
- ## ✅ 開發完成
275
-
276
- ### 🤖 AI 修復說明
277
- 實作了 X 功能,修改了 Y 元件
278
-
279
- ### 📝 Commit Info
280
- **Commit:** [abc1234](https://github.com/...)
281
- **Message:** feat: implement feature X
282
-
283
- ### 📊 Changes
284
- src/components/X.vue | 50 +++
285
- src/utils/Y.ts | 20 +-
286
- 2 files changed, 60 insertions(+), 10 deletions(-)
287
- ```
288
-
289
- ### 情境 4:團隊協作過濾
290
-
291
- 前端工程師只想看前端任務:
292
- ```toon
293
- # local.toon
294
- current_user: alice
295
- team: frontend
296
- label: Frontend
297
- exclude_labels[1]:
298
- - Bug
299
- exclude_assignees[2]:
300
- - bob # 排除後端同事的任務
301
- - charlie
302
- ```
303
-
304
- 後端工程師的設定(多團隊支援):
305
- ```toon
306
- # local.toon
307
- current_user: bob
308
- team: backend
309
- teams[2]:
310
- - backend
311
- - devops
312
- label: Backend
313
- ```
314
-
315
- ### 情境 5:狀態管理
316
-
317
- ```bash
318
- # 查看當前進行中任務的詳細資訊
319
- ttt status
320
-
321
- # 查看特定任務狀態
322
- ttt status MP-624
323
-
324
- # 快速移動狀態
325
- ttt status MP-624 --set +1 # 移動到下一狀態
326
-
327
- # 配置 Linear 狀態映射
328
- ttt config status # 互動式配置
329
-
330
- # 配置過濾器
331
- ttt config filters # 設定 exclude_labels, exclude_assignees
332
- ```
333
-
334
- ### 情境 6:多專案管理
335
-
336
- ```bash
337
- # 專案 A
338
- cd project-a
339
- ttt sync -d .ttt
340
-
341
- # 專案 B(不同 Linear 團隊)
342
- cd ../project-b
343
- ttt init -d .ttt # 初始化不同的配置
344
- ttt sync -d .ttt
345
- ```
346
-
347
- ### 情境 7:CI/CD 整合
348
-
349
- ```yaml
350
- # .github/workflows/sync.yml
351
- name: Sync Linear Tasks
352
- on:
353
- schedule:
354
- - cron: '0 9 * * 1-5' # 週一到週五早上 9 點
355
- jobs:
356
- sync:
357
- runs-on: ubuntu-latest
358
- steps:
359
- - uses: actions/checkout@v4
360
- - run: npm install -g team-toon-tack
361
- - run: ttt sync -d .ttt
362
- env:
363
- LINEAR_API_KEY: ${{ secrets.LINEAR_API_KEY }}
364
- - run: |
365
- git add .ttt/cycle.toon
366
- git commit -m "chore: sync linear tasks" || true
367
- git push
368
- ```
369
-
370
- ## 指令參考
51
+ ## CLI 參考
371
52
 
372
53
  ### `ttt init`
373
54
 
374
- 初始化配置檔,從 Linear 抓取團隊資料。
55
+ 在當前目錄初始化配置。
375
56
 
376
57
  ```bash
377
- ttt init [options]
378
-
379
- 選項:
380
- -d, --dir <path> 配置目錄(預設:當前目錄)
381
- -k, --api-key <key> Linear API 金鑰
382
- -u, --user <email> 預選使用者
383
- -l, --label <name> 預設標籤過濾
384
- -f, --force 覆蓋現有配置
385
- -y, --yes 非互動模式
58
+ ttt init # 互動模式
59
+ ttt init --user alice@example.com # 預選使用者
60
+ ttt init --label Frontend # 設定預設標籤
61
+ ttt init --force # 覆蓋現有配置
386
62
  ```
387
63
 
388
64
  ### `ttt sync`
389
65
 
390
- 從 Linear 同步任務到本地。
66
+ 從 Linear 同步當前 cycle 的 issue。
391
67
 
392
68
  ```bash
393
- ttt sync [issue-id] [options]
394
-
395
- 參數:
396
- issue-id 可選。只同步此特定任務(如 MP-624)
397
-
398
- 選項:
399
- -d, --dir <path> 配置目錄
400
-
401
- 範例:
402
- ttt sync # 同步所有符合條件的任務
403
- ttt sync MP-624 # 只同步此特定任務
69
+ ttt sync # 同步所有符合條件的 issue
70
+ ttt sync MP-123 # 只同步特定 issue
71
+ ttt sync --update # 將本地狀態推送到 Linear(local 模式用)
404
72
  ```
405
73
 
406
74
  ### `ttt work-on`
@@ -408,13 +76,9 @@ ttt sync [issue-id] [options]
408
76
  開始處理任務。
409
77
 
410
78
  ```bash
411
- ttt work-on [issue-id] [options]
412
-
413
- 參數:
414
- issue-id 任務編號(如 MP-624)或 "next"
415
-
416
- 選項:
417
- -d, --dir <path> 配置目錄
79
+ ttt work-on # 互動選擇
80
+ ttt work-on MP-123 # 指定 issue
81
+ ttt work-on next # 自動選擇最高優先級
418
82
  ```
419
83
 
420
84
  ### `ttt done`
@@ -422,14 +86,9 @@ ttt work-on [issue-id] [options]
422
86
  標記任務完成。
423
87
 
424
88
  ```bash
425
- ttt done [issue-id] [options]
426
-
427
- 參數:
428
- issue-id 任務編號(可選)
429
-
430
- 選項:
431
- -d, --dir <path> 配置目錄
432
- -m, --message <msg> 完成說明
89
+ ttt done # 若只有一個進行中,自動選擇
90
+ ttt done MP-123 # 指定 issue
91
+ ttt done -m "修復了錯誤" # 附上完成說明
433
92
  ```
434
93
 
435
94
  ### `ttt status`
@@ -437,27 +96,11 @@ ttt done [issue-id] [options]
437
96
  顯示或修改任務狀態。
438
97
 
439
98
  ```bash
440
- ttt status [issue-id] [--set <status>]
441
-
442
- 參數:
443
- issue-id 任務編號(可選,預設顯示進行中任務)
444
-
445
- 選項:
446
- -s, --set <status> 設定狀態
447
-
448
- 狀態選項:
449
- +1, -1, +2, -2 相對移動狀態
450
- pending 設為待處理
451
- in-progress 設為進行中
452
- completed 設為已完成
453
- blocked 設為後端阻擋
454
- todo, done, testing 設定 Linear 狀態
455
-
456
- 範例:
457
- ttt status # 顯示當前進行中任務
458
- ttt status MP-624 # 顯示特定任務狀態
459
- ttt status MP-624 --set +1 # 移動到下一狀態
460
- ttt status MP-624 --set done # 標記為完成
99
+ ttt status # 顯示當前進行中的任務
100
+ ttt status MP-123 # 顯示特定 issue 狀態
101
+ ttt status MP-123 --set +1 # 移動到下一狀態
102
+ ttt status MP-123 --set done # 標記為完成
103
+ ttt status MP-123 --set blocked # 設為阻塞(等待外部依賴)
461
104
  ```
462
105
 
463
106
  ### `ttt config`
@@ -465,60 +108,31 @@ ttt status [issue-id] [--set <status>]
465
108
  配置設定。
466
109
 
467
110
  ```bash
468
- ttt config [subcommand]
469
-
470
- 子指令:
471
- show 顯示當前配置(預設)
472
- status 配置狀態映射(todo, in_progress, done, testing)
473
- filters 配置過濾器(label, exclude_labels, exclude_assignees)
474
- teams 配置團隊選擇(多團隊支援)
475
-
476
- 範例:
477
- ttt config # 顯示當前配置
478
- ttt config status # 配置狀態映射
479
- ttt config filters # 配置過濾器
480
- ttt config teams # 配置團隊選擇
111
+ ttt config # 顯示當前配置
112
+ ttt config status # 配置狀態映射
113
+ ttt config filters # 配置標籤/使用者過濾
114
+ ttt config teams # 配置多團隊選擇
481
115
  ```
482
116
 
483
- ## 環境變數
484
-
485
- | 變數 | 說明 |
486
- |------|------|
487
- | `LINEAR_API_KEY` | **必填**。Linear API 金鑰([取得方式](https://linear.app/settings/api)) |
488
- | `TOON_DIR` | 配置目錄路徑(可取代 `-d` 參數) |
489
-
490
- ## 常見問題
491
-
492
- ### Q: 為什麼用 TOON 格式?
493
-
494
- TOON 是一種人類可讀的資料格式,類似 YAML 但更簡潔。相比 JSON:
495
- - 更容易手動編輯
496
- - 支援註解
497
- - AI 助手更容易理解
117
+ ## 配置說明
498
118
 
499
- ### Q: config.ttt 可以提交到 Git 嗎?
119
+ ### 目錄結構
500
120
 
501
- 可以,但建議 gitignore。因為包含:
502
- - 團隊成員的 email
503
- - Linear 內部 UUID
504
-
505
- 如果是私有倉庫且團隊成員都有 Linear 存取權,提交是安全的。
506
-
507
- ### Q: 如何處理衝突?
508
-
509
- `cycle.toon` 是自動產生的,直接用 `ttt sync` 重新同步即可。
121
+ ```
122
+ your-project/
123
+ └── .ttt/
124
+ ├── config.toon # 團隊配置(建議 gitignore)
125
+ ├── local.toon # 個人設定(gitignore)
126
+ ├── cycle.toon # 當前 cycle 資料(自動產生)
127
+ └── output/ # 下載的附件(圖片、檔案)
128
+ ```
510
129
 
511
- ### Q: 支援哪些 Linear 功能?
130
+ ### 環境變數
512
131
 
513
- - Cycle 任務同步
514
- - ✅ 單一任務同步 (`ttt sync MP-624`)
515
- - 狀態雙向同步
516
- - 自訂狀態映射(`ttt config status`)
517
- - ✅ 附件和留言讀取
518
- - ✅ 父子任務關聯
519
- - ✅ 優先級排序
520
- - ✅ 多團隊支援
521
- - ✅ 標籤/用戶過濾
132
+ | 變數 | 說明 |
133
+ |------|------|
134
+ | `LINEAR_API_KEY` | **必填**。你的 Linear API 金鑰 |
135
+ | `TOON_DIR` | 配置目錄(預設:`.ttt`) |
522
136
 
523
137
  ## 授權
524
138
 
@@ -104,8 +104,11 @@ Examples:
104
104
  });
105
105
  aiMessage = aiMsgResponse.aiMessage || "";
106
106
  }
107
- // Update Linear
108
- if (task.linearId && process.env.LINEAR_API_KEY) {
107
+ // Update Linear (only if status_source is 'remote' or not set)
108
+ const statusSource = localConfig.status_source || "remote";
109
+ if (task.linearId &&
110
+ process.env.LINEAR_API_KEY &&
111
+ statusSource === "remote") {
109
112
  const transitions = getStatusTransitions(config);
110
113
  // Update issue to Done
111
114
  const success = await updateIssueStatus(task.linearId, transitions.done, config, localConfig.team);
@@ -129,7 +132,20 @@ Examples:
129
132
  if (parentIssue) {
130
133
  const parentTeam = await parentIssue.team;
131
134
  if (parentTeam) {
132
- const parentStates = await getWorkflowStates(config, localConfig.team);
135
+ // Determine which team key to use for parent's workflow states
136
+ // If qa_pm_team is configured and matches parent's team, use it
137
+ // Otherwise, try to find the team key from config
138
+ let parentTeamKey = localConfig.team;
139
+ const teamEntries = Object.entries(config.teams);
140
+ const matchingTeam = teamEntries.find(([_, t]) => t.id === parentTeam.id);
141
+ if (matchingTeam) {
142
+ parentTeamKey = matchingTeam[0];
143
+ }
144
+ else if (localConfig.qa_pm_team) {
145
+ // Fallback to qa_pm_team if configured
146
+ parentTeamKey = localConfig.qa_pm_team;
147
+ }
148
+ const parentStates = await getWorkflowStates(config, parentTeamKey);
133
149
  const testingState = parentStates.find((s) => s.name === transitions.testing);
134
150
  if (testingState) {
135
151
  await client.updateIssue(parentIssue.id, {
@@ -145,6 +161,10 @@ Examples:
145
161
  }
146
162
  }
147
163
  }
164
+ else if (statusSource === "local") {
165
+ console.log(`Local: ${task.id} marked as completed`);
166
+ console.log(`(Linear status not updated - use 'sync --update' to push)`);
167
+ }
148
168
  // Sync full issue data from Linear (including new comment)
149
169
  const syncedTask = await syncSingleIssue(task.id, {
150
170
  config,