team-toon-tack 2.3.2 → 2.3.4

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.
@@ -611,8 +611,6 @@ async function init() {
611
611
  console.log(` ✓ ${paths.localPath}`);
612
612
  // Update .gitignore (always use relative path .ttt)
613
613
  await updateGitignore(".ttt", options.interactive ?? true);
614
- // Show Claude Code plugin installation instructions
615
- showPluginInstallInstructions();
616
614
  // Summary
617
615
  console.log("\n✅ Initialization complete!\n");
618
616
  console.log("Configuration summary:");
@@ -642,9 +640,19 @@ async function init() {
642
640
  console.log(` Blocked: ${statusTransitions.blocked}`);
643
641
  }
644
642
  console.log("\nNext steps:");
645
- console.log(" 1. Set LINEAR_API_KEY in your shell profile:");
646
- console.log(` export LINEAR_API_KEY="${apiKey}"`);
647
- console.log(" 2. Run sync: ttt sync");
648
- console.log(" 3. Start working: ttt work-on");
643
+ if (!process.env.LINEAR_API_KEY) {
644
+ // Show partial key for confirmation (first 12 chars + masked)
645
+ const maskedKey = `${apiKey.slice(0, 12)}...${"*".repeat(8)}`;
646
+ console.log(" 1. Set LINEAR_API_KEY in your shell profile:");
647
+ console.log(` export LINEAR_API_KEY="${maskedKey}"`);
648
+ console.log(" 2. Run sync: ttt sync");
649
+ console.log(" 3. Start working: ttt work-on");
650
+ }
651
+ else {
652
+ console.log(" 1. Run sync: ttt sync");
653
+ console.log(" 2. Start working: ttt work-on");
654
+ }
655
+ // Show Claude Code plugin installation instructions at the end
656
+ showPluginInstallInstructions();
649
657
  }
650
658
  init().catch(console.error);
@@ -1,4 +1,4 @@
1
- import { displayTaskFull, PRIORITY_LABELS, getStatusIcon } from "./lib/display.js";
1
+ import { displayTaskFull, getStatusIcon, PRIORITY_LABELS, } from "./lib/display.js";
2
2
  import { fetchIssueDetail } from "./lib/sync.js";
3
3
  import { getLinearClient, getTeamId, loadConfig, loadCycleData, loadLocalConfig, } from "./utils.js";
4
4
  function taskToMarkdown(task) {
@@ -110,7 +110,9 @@ async function searchIssuesFromLinear(filters) {
110
110
  issueFilter.assignee = { null: true };
111
111
  }
112
112
  else {
113
- issueFilter.assignee = { email: { containsIgnoreCase: filters.assignee } };
113
+ issueFilter.assignee = {
114
+ email: { containsIgnoreCase: filters.assignee },
115
+ };
114
116
  }
115
117
  }
116
118
  if (filters.priority !== undefined) {
@@ -4,7 +4,7 @@ async function sync() {
4
4
  const args = process.argv.slice(2);
5
5
  // Handle help flag
6
6
  if (args.includes("--help") || args.includes("-h")) {
7
- console.log(`Usage: ttt sync [issue-id] [--update]
7
+ console.log(`Usage: ttt sync [issue-id] [--all] [--update]
8
8
 
9
9
  Sync issues from Linear to local cycle.ttt file.
10
10
 
@@ -12,25 +12,27 @@ Arguments:
12
12
  issue-id Optional. Sync only this specific issue (e.g., MP-624)
13
13
 
14
14
  Options:
15
+ --all Sync all issues regardless of status (default: only Todo/In Progress)
15
16
  --update Push local status changes to Linear (for local mode users)
16
17
  This updates Linear with your local in-progress/completed statuses
17
18
 
18
19
  What it does:
19
20
  - Fetches active cycle from Linear
20
- - Downloads all issues in the cycle (regardless of status)
21
+ - Downloads issues with Todo/In Progress status (or all with --all)
21
22
  - Filters by label if configured
22
23
  - Preserves local status for existing tasks
23
24
  - Updates config with new cycle info
24
25
 
25
26
  Examples:
26
- ttt sync # Sync all issues in current cycle
27
+ ttt sync # Sync Todo/In Progress issues
28
+ ttt sync --all # Sync all issues regardless of status
27
29
  ttt sync MP-624 # Sync only this specific issue
28
- ttt sync --update # Push local changes to Linear, then sync
29
- ttt sync -d .ttt # Sync using .ttt directory`);
30
+ ttt sync --update # Push local changes to Linear, then sync`);
30
31
  process.exit(0);
31
32
  }
32
- // Check for --update flag
33
+ // Check for flags
33
34
  const shouldUpdate = args.includes("--update");
35
+ const syncAll = args.includes("--all");
34
36
  // Parse issue ID argument (if provided)
35
37
  const singleIssueId = args.find((arg) => !arg.startsWith("-") && arg.match(/^[A-Z]+-\d+$/i));
36
38
  const config = await loadConfig();
@@ -151,6 +153,7 @@ Examples:
151
153
  const existingTasksMap = new Map(existingData?.tasks.map((t) => [t.id, t]));
152
154
  // Phase 4: Fetch current issues with full content
153
155
  const filterLabel = localConfig.label;
156
+ const syncStatuses = [statusTransitions.todo, statusTransitions.in_progress];
154
157
  let issues;
155
158
  if (singleIssueId) {
156
159
  // Sync single issue by ID
@@ -164,13 +167,20 @@ Examples:
164
167
  issues = { nodes: [matchingIssue] };
165
168
  }
166
169
  else {
167
- // Sync all matching issues
168
- console.log(`Fetching all issues in current cycle${filterLabel ? ` with label: ${filterLabel}` : ""}...`);
169
- // Build filter - label is optional, no status filter
170
+ // Build status filter description
171
+ const statusDesc = syncAll
172
+ ? "all statuses"
173
+ : `${syncStatuses.join("/")} status`;
174
+ console.log(`Fetching issues (${statusDesc})${filterLabel ? ` with label: ${filterLabel}` : ""}...`);
175
+ // Build filter - label is optional
170
176
  const issueFilter = {
171
177
  team: { id: { eq: teamId } },
172
178
  cycle: { id: { eq: cycleId } },
173
179
  };
180
+ // Only filter by status if not syncing all
181
+ if (!syncAll) {
182
+ issueFilter.state = { name: { in: syncStatuses } };
183
+ }
174
184
  if (filterLabel) {
175
185
  issueFilter.labels = { name: { eq: filterLabel } };
176
186
  }
@@ -182,9 +192,16 @@ Examples:
182
192
  if (issues.nodes.length === 0) {
183
193
  console.log(`No issues found in current cycle${filterLabel ? ` with label: ${filterLabel}` : ""}.`);
184
194
  }
195
+ else {
196
+ console.log(`Found ${issues.nodes.length} issues. Processing...`);
197
+ }
185
198
  const tasks = [];
186
199
  let updatedCount = 0;
200
+ const totalIssues = issues.nodes.length;
201
+ let processedCount = 0;
187
202
  for (const issueNode of issues.nodes) {
203
+ processedCount++;
204
+ process.stdout.write(`\r Processing ${processedCount}/${totalIssues}...`);
188
205
  // Fetch full issue to get all relations (searchIssues returns IssueSearchResult which lacks some methods)
189
206
  const issue = await client.issue(issueNode.id);
190
207
  const assignee = await issue.assignee;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "team-toon-tack",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "Linear task sync & management CLI with TOON format",
5
5
  "type": "module",
6
6
  "bin": {