team-toon-tack 1.0.12 → 1.6.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.md CHANGED
@@ -57,7 +57,8 @@ ttt init -y # Non-interactive mode
57
57
  Sync current cycle issues from Linear.
58
58
 
59
59
  ```bash
60
- ttt sync
60
+ ttt sync # Sync all matching issues
61
+ ttt sync MP-123 # Sync only this specific issue
61
62
  ```
62
63
 
63
64
  ### `ttt work-on`
@@ -80,6 +81,31 @@ ttt done MP-123 # Specific issue
80
81
  ttt done -m "Fixed the bug" # With completion message
81
82
  ```
82
83
 
84
+ ### `ttt status`
85
+
86
+ Show or modify task status.
87
+
88
+ ```bash
89
+ ttt status # Show current in-progress task
90
+ ttt status MP-123 # Show specific issue status
91
+ ttt status MP-123 --set +1 # Move to next status
92
+ ttt status MP-123 --set done # Mark as done
93
+ ttt status --set pending # Reset current task
94
+ ```
95
+
96
+ Status options: `+1`, `-1`, `+2`, `-2`, `pending`, `in-progress`, `completed`, `blocked`, `todo`, `done`, `testing`
97
+
98
+ ### `ttt config`
99
+
100
+ Configure settings.
101
+
102
+ ```bash
103
+ ttt config # Show current configuration
104
+ ttt config status # Configure status mappings
105
+ ttt config filters # Configure label/user filters
106
+ ttt config teams # Configure multi-team selection
107
+ ```
108
+
83
109
  ## Configuration
84
110
 
85
111
  ### Directory Structure
@@ -88,9 +114,10 @@ After `ttt init`, your project will have:
88
114
 
89
115
  ```
90
116
  your-project/
91
- ├── config.ttt # Team configuration (gitignore recommended)
92
- ├── local.ttt # Personal settings (gitignore)
93
- └── cycle.ttt # Current cycle data (gitignore, auto-generated)
117
+ └── .ttt/ # Config directory
118
+ ├── config.toon # Team configuration (gitignore recommended)
119
+ ├── local.toon # Personal settings (gitignore)
120
+ └── cycle.toon # Current cycle data (gitignore, auto-generated)
94
121
  ```
95
122
 
96
123
  ### Custom Config Directory
@@ -104,7 +131,7 @@ export TOON_DIR=./team
104
131
  ttt sync
105
132
  ```
106
133
 
107
- ### config.ttt
134
+ ### config.toon
108
135
 
109
136
  Team-wide configuration (fetched from Linear):
110
137
 
@@ -130,22 +157,46 @@ current_cycle:
130
157
  name: Cycle #1
131
158
  ```
132
159
 
133
- ### local.ttt
160
+ ### local.toon
134
161
 
135
162
  Personal settings:
136
163
 
137
164
  ```toon
138
165
  current_user: alice
166
+ team: frontend
167
+ teams[2]:
168
+ - frontend
169
+ - backend
139
170
  label: Frontend
140
- exclude_assignees[1]: bob
171
+ exclude_labels[1]:
172
+ - Bug
173
+ exclude_assignees[1]:
174
+ - bob
141
175
  ```
142
176
 
143
177
  | Field | Description |
144
178
  |-------|-------------|
145
- | `current_user` | Your user key from config.ttt |
179
+ | `current_user` | Your user key from config.toon |
180
+ | `team` | Primary team key |
181
+ | `teams` | Multiple teams to sync (optional) |
146
182
  | `label` | Filter issues by label (optional) |
183
+ | `exclude_labels` | Exclude issues with these labels (optional) |
147
184
  | `exclude_assignees` | Hide issues from these users (optional) |
148
185
 
186
+ ### config.toon - Status Mappings
187
+
188
+ Configure which Linear statuses map to local states:
189
+
190
+ ```toon
191
+ status_transitions:
192
+ todo: Todo
193
+ in_progress: In Progress
194
+ done: Done
195
+ testing: Testing
196
+ ```
197
+
198
+ Run `ttt config status` to configure interactively.
199
+
149
200
  ## Environment Variables
150
201
 
151
202
  | Variable | Description |
package/README.zh-TW.md CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
  ```
20
20
  ┌─────────────┐ ┌──────────────┐ ┌─────────────┐
21
- │ Linear │────▶│ ttt sync │────▶│ cycle.ttt
21
+ │ Linear │────▶│ ttt sync │────▶│ cycle.toon
22
22
  │ (雲端) │ │ │ │ (本地) │
23
23
  └─────────────┘ └──────────────┘ └─────────────┘
24
24
 
@@ -34,10 +34,10 @@
34
34
  1. **同步 (sync)**
35
35
  - 從 Linear API 抓取當前 Cycle 的任務
36
36
  - 根據 `local.ttt` 設定過濾(標籤、排除指派人)
37
- - 寫入 `cycle.ttt`,包含完整任務資訊
37
+ - 寫入 `cycle.toon`,包含完整任務資訊
38
38
 
39
39
  2. **開始任務 (work-on)**
40
- - 讀取 `cycle.ttt` 中的待處理任務
40
+ - 讀取 `cycle.toon` 中的待處理任務
41
41
  - 更新本地狀態為 `in-progress`
42
42
  - 同步更新 Linear 狀態為 "In Progress"
43
43
 
@@ -51,19 +51,22 @@
51
51
 
52
52
  ```
53
53
  .ttt/ # 配置目錄(建議 gitignore)
54
- ├── config.ttt # 團隊配置
54
+ ├── config.toon # 團隊配置
55
55
  │ ├── teams # Linear 團隊 ID 映射
56
56
  │ ├── users # 成員 ID/email 映射
57
57
  │ ├── labels # 標籤 ID 映射
58
- │ ├── statuses # 狀態定義
58
+ │ ├── status_transitions # 狀態映射配置
59
59
  │ └── current_cycle # 當前 Cycle 資訊
60
60
 
61
- ├── local.ttt # 個人設定(必須 gitignore)
61
+ ├── local.toon # 個人設定(必須 gitignore)
62
62
  │ ├── current_user # 你的 user key
63
- │ ├── label # 過濾標籤
63
+ │ ├── team # 主要團隊
64
+ │ ├── teams # 多團隊同步(可選)
65
+ │ ├── label # 過濾標籤(可選)
66
+ │ ├── exclude_labels # 排除的標籤
64
67
  │ └── exclude_assignees # 排除的指派人
65
68
 
66
- └── cycle.ttt # 任務資料(自動產生)
69
+ └── cycle.toon # 任務資料(自動產生)
67
70
  ├── cycleId # Cycle UUID
68
71
  ├── cycleName # Cycle 名稱
69
72
  ├── updatedAt # 最後同步時間
@@ -120,7 +123,7 @@ ttt sync -d .ttt
120
123
  ttt work-on -d .ttt
121
124
 
122
125
  # Claude Code 現在可以讀取任務內容
123
- # 在 .ttt/cycle.ttt 中找到任務描述、附件等
126
+ # 在 .ttt/cycle.toon 中找到任務描述、附件等
124
127
  ```
125
128
 
126
129
  ### 情境 2:搭配 Claude Code 自動化
@@ -137,7 +140,7 @@ description: Sync Linear issues to local TOON file
137
140
 
138
141
  # Sync Linear Issues
139
142
 
140
- Fetch current cycle's issues from Linear to `.ttt/cycle.ttt`.
143
+ Fetch current cycle's issues from Linear to `.ttt/cycle.toon`.
141
144
 
142
145
  ## Process
143
146
 
@@ -216,7 +219,7 @@ Mark a task as done and update Linear with commit details.
216
219
 
217
220
  ### 1. Determine Issue ID
218
221
 
219
- Check `.ttt/cycle.ttt` for tasks with `localStatus: in-progress`.
222
+ Check `.ttt/cycle.toon` for tasks with `localStatus: in-progress`.
220
223
 
221
224
  ### 2. Write Fix Summary
222
225
 
@@ -236,7 +239,7 @@ ttt done -d .ttt $ARGUMENTS -m "修復說明"
236
239
  - Linear issue status → "Done"
237
240
  - Adds comment with commit hash, message, and diff summary
238
241
  - Parent issue (if exists) → "Testing"
239
- - Local status → `completed` in `.ttt/cycle.ttt`
242
+ - Local status → `completed` in `.ttt/cycle.toon`
240
243
  ```
241
244
 
242
245
  #### 使用方式
@@ -287,21 +290,48 @@ Linear 上會自動新增留言:
287
290
 
288
291
  前端工程師只想看前端任務:
289
292
  ```toon
290
- # local.ttt
293
+ # local.toon
291
294
  current_user: alice
295
+ team: frontend
292
296
  label: Frontend
293
- exclude_assignees[1]: bob # 排除後端同事的任務
294
- exclude_assignees[2]: charlie
297
+ exclude_labels[1]:
298
+ - Bug
299
+ exclude_assignees[2]:
300
+ - bob # 排除後端同事的任務
301
+ - charlie
295
302
  ```
296
303
 
297
- 後端工程師的設定:
304
+ 後端工程師的設定(多團隊支援):
298
305
  ```toon
299
- # local.ttt
306
+ # local.toon
300
307
  current_user: bob
308
+ team: backend
309
+ teams[2]:
310
+ - backend
311
+ - devops
301
312
  label: Backend
302
313
  ```
303
314
 
304
- ### 情境 5:多專案管理
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:多專案管理
305
335
 
306
336
  ```bash
307
337
  # 專案 A
@@ -314,7 +344,7 @@ ttt init -d .ttt # 初始化不同的配置
314
344
  ttt sync -d .ttt
315
345
  ```
316
346
 
317
- ### 情境 6:CI/CD 整合
347
+ ### 情境 7:CI/CD 整合
318
348
 
319
349
  ```yaml
320
350
  # .github/workflows/sync.yml
@@ -332,7 +362,7 @@ jobs:
332
362
  env:
333
363
  LINEAR_API_KEY: ${{ secrets.LINEAR_API_KEY }}
334
364
  - run: |
335
- git add .ttt/cycle.ttt
365
+ git add .ttt/cycle.toon
336
366
  git commit -m "chore: sync linear tasks" || true
337
367
  git push
338
368
  ```
@@ -360,10 +390,17 @@ ttt init [options]
360
390
  從 Linear 同步任務到本地。
361
391
 
362
392
  ```bash
363
- ttt sync [options]
393
+ ttt sync [issue-id] [options]
394
+
395
+ 參數:
396
+ issue-id 可選。只同步此特定任務(如 MP-624)
364
397
 
365
398
  選項:
366
399
  -d, --dir <path> 配置目錄
400
+
401
+ 範例:
402
+ ttt sync # 同步所有符合條件的任務
403
+ ttt sync MP-624 # 只同步此特定任務
367
404
  ```
368
405
 
369
406
  ### `ttt work-on`
@@ -395,6 +432,54 @@ ttt done [issue-id] [options]
395
432
  -m, --message <msg> 完成說明
396
433
  ```
397
434
 
435
+ ### `ttt status`
436
+
437
+ 顯示或修改任務狀態。
438
+
439
+ ```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 # 標記為完成
461
+ ```
462
+
463
+ ### `ttt config`
464
+
465
+ 配置設定。
466
+
467
+ ```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 # 配置團隊選擇
481
+ ```
482
+
398
483
  ## 環境變數
399
484
 
400
485
  | 變數 | 說明 |
@@ -421,15 +506,19 @@ TOON 是一種人類可讀的資料格式,類似 YAML 但更簡潔。相比 JS
421
506
 
422
507
  ### Q: 如何處理衝突?
423
508
 
424
- `cycle.ttt` 是自動產生的,直接用 `ttt sync` 重新同步即可。
509
+ `cycle.toon` 是自動產生的,直接用 `ttt sync` 重新同步即可。
425
510
 
426
511
  ### Q: 支援哪些 Linear 功能?
427
512
 
428
513
  - ✅ Cycle 任務同步
514
+ - ✅ 單一任務同步 (`ttt sync MP-624`)
429
515
  - ✅ 狀態雙向同步
516
+ - ✅ 自訂狀態映射(`ttt config status`)
430
517
  - ✅ 附件和留言讀取
431
518
  - ✅ 父子任務關聯
432
519
  - ✅ 優先級排序
520
+ - ✅ 多團隊支援
521
+ - ✅ 標籤/用戶過濾
433
522
 
434
523
  ## 授權
435
524
 
@@ -1,12 +1,21 @@
1
1
  #!/usr/bin/env node
2
- import { resolve } from 'node:path';
3
- import { readFileSync } from 'node:fs';
4
- import { fileURLToPath } from 'node:url';
5
- import { dirname, join } from 'node:path';
2
+ import { readFileSync } from "node:fs";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
6
5
  const __dirname = dirname(fileURLToPath(import.meta.url));
7
- const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
6
+ // When running from dist/bin/cli.js, we need to go up two levels to find package.json
7
+ const pkg = JSON.parse(readFileSync(join(__dirname, "..", "..", "package.json"), "utf-8"));
8
8
  const VERSION = pkg.version;
9
- const COMMANDS = ['init', 'sync', 'work-on', 'done', 'help', 'version'];
9
+ const COMMANDS = [
10
+ "init",
11
+ "sync",
12
+ "work-on",
13
+ "done",
14
+ "status",
15
+ "config",
16
+ "help",
17
+ "version",
18
+ ];
10
19
  function printHelp() {
11
20
  console.log(`
12
21
  team-toon-tack (ttt) - Linear task sync & management CLI
@@ -19,6 +28,8 @@ COMMANDS:
19
28
  sync Sync issues from Linear to local cycle.ttt
20
29
  work-on Start working on a task (interactive or by ID)
21
30
  done Mark current task as completed
31
+ status Show or modify task status
32
+ config Configure settings (status mappings, filters)
22
33
  help Show this help message
23
34
  version Show version
24
35
 
@@ -47,12 +58,12 @@ function printVersion() {
47
58
  console.log(`team-toon-tack v${VERSION}`);
48
59
  }
49
60
  function parseGlobalArgs(args) {
50
- let dir = process.env.TOON_DIR || resolve(process.cwd(), '.ttt');
61
+ let dir = process.env.TOON_DIR || resolve(process.cwd(), ".ttt");
51
62
  const commandArgs = [];
52
63
  for (let i = 0; i < args.length; i++) {
53
64
  const arg = args[i];
54
- if (arg === '-d' || arg === '--dir') {
55
- dir = resolve(args[++i] || '.');
65
+ if (arg === "-d" || arg === "--dir") {
66
+ dir = resolve(args[++i] || ".");
56
67
  }
57
68
  else {
58
69
  commandArgs.push(arg);
@@ -62,11 +73,14 @@ function parseGlobalArgs(args) {
62
73
  }
63
74
  async function main() {
64
75
  const args = process.argv.slice(2);
65
- if (args.length === 0 || args[0] === 'help' || args[0] === '-h' || args[0] === '--help') {
76
+ if (args.length === 0 ||
77
+ args[0] === "help" ||
78
+ args[0] === "-h" ||
79
+ args[0] === "--help") {
66
80
  printHelp();
67
81
  process.exit(0);
68
82
  }
69
- if (args[0] === 'version' || args[0] === '-v' || args[0] === '--version') {
83
+ if (args[0] === "version" || args[0] === "-v" || args[0] === "--version") {
70
84
  printVersion();
71
85
  process.exit(0);
72
86
  }
@@ -81,24 +95,32 @@ async function main() {
81
95
  process.exit(1);
82
96
  }
83
97
  // Import and run the appropriate script
84
- const scriptDir = new URL('../scripts/', import.meta.url).pathname;
98
+ const scriptDir = new URL("../scripts/", import.meta.url).pathname;
85
99
  try {
86
100
  switch (command) {
87
- case 'init':
88
- process.argv = ['node', 'init.js', ...commandArgs];
101
+ case "init":
102
+ process.argv = ["node", "init.js", ...commandArgs];
89
103
  await import(`${scriptDir}init.js`);
90
104
  break;
91
- case 'sync':
105
+ case "sync":
92
106
  await import(`${scriptDir}sync.js`);
93
107
  break;
94
- case 'work-on':
95
- process.argv = ['node', 'work-on.js', ...commandArgs];
108
+ case "work-on":
109
+ process.argv = ["node", "work-on.js", ...commandArgs];
96
110
  await import(`${scriptDir}work-on.js`);
97
111
  break;
98
- case 'done':
99
- process.argv = ['node', 'done-job.js', ...commandArgs];
112
+ case "done":
113
+ process.argv = ["node", "done-job.js", ...commandArgs];
100
114
  await import(`${scriptDir}done-job.js`);
101
115
  break;
116
+ case "status":
117
+ process.argv = ["node", "status.js", ...commandArgs];
118
+ await import(`${scriptDir}status.js`);
119
+ break;
120
+ case "config":
121
+ process.argv = ["node", "config.js", ...commandArgs];
122
+ await import(`${scriptDir}config.js`);
123
+ break;
102
124
  }
103
125
  }
104
126
  catch (error) {