team-toon-tack 2.1.0 → 2.3.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.
@@ -400,147 +400,39 @@ async function updateGitignore(tttDir, interactive) {
400
400
  // Silently ignore gitignore errors
401
401
  }
402
402
  }
403
- async function installClaudeCommands(interactive, statusSource) {
403
+ async function showPluginInstallInstructions(interactive) {
404
404
  if (!interactive) {
405
- return { installed: false, prefix: "" };
405
+ return false;
406
406
  }
407
- console.log("\n🤖 Claude Code Commands:");
408
- // Ask if user wants to install commands
409
- const { install } = await prompts({
407
+ console.log("\n🤖 Claude Code Plugin:");
408
+ const { showInstructions } = await prompts({
410
409
  type: "confirm",
411
- name: "install",
412
- message: "Install Claude Code commands? (work-on, done-job, sync-linear)",
410
+ name: "showInstructions",
411
+ message: "Show Claude Code plugin installation instructions? (provides /ttt-* commands)",
413
412
  initial: true,
414
413
  });
415
- if (!install) {
416
- return { installed: false, prefix: "" };
417
- }
418
- // Ask for prefix
419
- const { prefixChoice } = await prompts({
420
- type: "select",
421
- name: "prefixChoice",
422
- message: "Command prefix style:",
423
- choices: [
424
- {
425
- title: "No prefix (recommended)",
426
- value: "",
427
- description: "/work-on, /done-job, /sync-linear",
428
- },
429
- {
430
- title: "ttt:",
431
- value: "ttt:",
432
- description: "/ttt:work-on, /ttt:done-job, /ttt:sync-linear",
433
- },
434
- {
435
- title: "linear:",
436
- value: "linear:",
437
- description: "/linear:work-on, /linear:done-job, /linear:sync-linear",
438
- },
439
- {
440
- title: "Custom...",
441
- value: "custom",
442
- description: "Enter your own prefix",
443
- },
444
- ],
445
- initial: 0,
446
- });
447
- let prefix = prefixChoice || "";
448
- if (prefixChoice === "custom") {
449
- const { customPrefix } = await prompts({
450
- type: "text",
451
- name: "customPrefix",
452
- message: "Enter custom prefix (e.g., 'my:'):",
453
- initial: "",
454
- });
455
- prefix = customPrefix || "";
456
- }
457
- // Find templates directory
458
- // Try multiple locations: installed package, local dev
459
- const possibleTemplatePaths = [
460
- path.join(__dirname, "..", "templates", "claude-code-commands"),
461
- path.join(__dirname, "..", "..", "templates", "claude-code-commands"),
462
- path.join(process.cwd(), "templates", "claude-code-commands"),
463
- ];
464
- let templateDir = null;
465
- for (const p of possibleTemplatePaths) {
466
- try {
467
- await fs.access(p);
468
- templateDir = p;
469
- break;
470
- }
471
- catch {
472
- // Try next path
473
- }
474
- }
475
- if (!templateDir) {
476
- // Try to get repo URL from package.json
477
- let repoUrl = "https://github.com/wayne930242/team-toon-tack";
478
- try {
479
- const pkgPaths = [
480
- path.join(__dirname, "..", "package.json"),
481
- path.join(__dirname, "..", "..", "package.json"),
482
- ];
483
- for (const pkgPath of pkgPaths) {
484
- try {
485
- const pkgContent = await fs.readFile(pkgPath, "utf-8");
486
- const pkg = JSON.parse(pkgContent);
487
- if (pkg.repository?.url) {
488
- // Parse git+https://github.com/user/repo.git format
489
- repoUrl = pkg.repository.url
490
- .replace(/^git\+/, "")
491
- .replace(/\.git$/, "");
492
- }
493
- break;
494
- }
495
- catch {
496
- // Try next path
497
- }
498
- }
499
- }
500
- catch {
501
- // Use default URL
502
- }
503
- console.log(" ⚠ Could not find command templates. Please copy manually from:");
504
- console.log(` ${repoUrl}/tree/main/templates/claude-code-commands`);
505
- return { installed: false, prefix };
506
- }
507
- // Create .claude/commands directory
508
- const commandsDir = path.join(process.cwd(), ".claude", "commands");
509
- await fs.mkdir(commandsDir, { recursive: true });
510
- // Copy and rename template files
511
- const templateFiles = await fs.readdir(templateDir);
512
- const commandFiles = templateFiles.filter((f) => f.endsWith(".md"));
513
- for (const file of commandFiles) {
514
- const baseName = file.replace(".md", "");
515
- const newFileName = prefix ? `${prefix}${baseName}.md` : file;
516
- const srcPath = path.join(templateDir, file);
517
- const destPath = path.join(commandsDir, newFileName);
518
- // Read template content
519
- let content = await fs.readFile(srcPath, "utf-8");
520
- // Update the name in frontmatter if prefix is used
521
- if (prefix) {
522
- content = content.replace(/^(---\s*\n[\s\S]*?name:\s*)(\S+)/m, `$1${prefix}${baseName}`);
523
- }
524
- // Modify content based on statusSource for work-on and done-job
525
- if (statusSource === "local") {
526
- if (baseName === "work-on" || baseName.endsWith("work-on")) {
527
- // Update description for local mode
528
- content = content.replace(/Select a task and update status to "In Progress" on both local and Linear\./, 'Select a task and update local status to "In Progress". (Linear will be updated when you run `sync --update`)');
529
- // Add reminder after Complete section
530
- content = content.replace(/Use `?\/done-job`? to mark task as completed/, "Use `/done-job` to mark task as completed\n\n### 7. Sync to Linear\n\nWhen ready to update Linear with all your changes:\n\n```bash\nttt sync --update\n```");
531
- }
532
- if (baseName === "done-job" || baseName.endsWith("done-job")) {
533
- // Update description for local mode
534
- content = content.replace(/Mark a task as done and update Linear with commit details\./, "Mark a task as done locally. (Run `ttt sync --update` to push changes to Linear)");
535
- // Add reminder at the end
536
- content = content.replace(/## What It Does\n\n- Linear issue status → "Done"/, "## What It Does\n\n- Local status → `completed`");
537
- content += `\n## Sync to Linear\n\nAfter completing tasks, push all changes to Linear:\n\n\`\`\`bash\nttt sync --update\n\`\`\`\n`;
538
- }
539
- }
540
- await fs.writeFile(destPath, content, "utf-8");
541
- console.log(` ✓ .claude/commands/${newFileName}`);
542
- }
543
- return { installed: true, prefix };
414
+ if (!showInstructions) {
415
+ return false;
416
+ }
417
+ console.log("\n┌─────────────────────────────────────────────────────────────┐");
418
+ console.log("│ Install team-toon-tack plugin in Claude Code: │");
419
+ console.log("├─────────────────────────────────────────────────────────────┤");
420
+ console.log("│ │");
421
+ console.log("│ 1. Add marketplace: │");
422
+ console.log("│ /plugin marketplace add wayne930242/team-toon-tack │");
423
+ console.log("│ │");
424
+ console.log("│ 2. Install plugin: │");
425
+ console.log("│ /plugin install team-toon-tack@wayne930242 │");
426
+ console.log("│ │");
427
+ console.log("│ Available commands after install: │");
428
+ console.log("│ /ttt-sync - Sync Linear issues │");
429
+ console.log("│ /ttt-work-on - Start working on a task │");
430
+ console.log("│ /ttt-done - Complete current task │");
431
+ console.log("│ /ttt-status - Show/modify task status │");
432
+ console.log("│ /ttt-get-issue - Fetch issue details │");
433
+ console.log("│ │");
434
+ console.log("└─────────────────────────────────────────────────────────────┘");
435
+ return true;
544
436
  }
545
437
  async function init() {
546
438
  const args = process.argv.slice(2);
@@ -732,8 +624,8 @@ async function init() {
732
624
  console.log(` ✓ ${paths.localPath}`);
733
625
  // Update .gitignore (always use relative path .ttt)
734
626
  await updateGitignore(".ttt", options.interactive ?? true);
735
- // Install Claude Code commands
736
- const { installed: commandsInstalled, prefix: commandPrefix } = await installClaudeCommands(options.interactive ?? true, statusSource);
627
+ // Show Claude Code plugin installation instructions
628
+ const pluginInstructionsShown = await showPluginInstallInstructions(options.interactive ?? true);
737
629
  // Summary
738
630
  console.log("\n✅ Initialization complete!\n");
739
631
  console.log("Configuration summary:");
@@ -762,21 +654,13 @@ async function init() {
762
654
  if (statusTransitions.blocked) {
763
655
  console.log(` Blocked: ${statusTransitions.blocked}`);
764
656
  }
765
- if (commandsInstalled) {
766
- const cmdPrefix = commandPrefix ? `${commandPrefix}` : "";
767
- console.log(` Claude commands: /${cmdPrefix}work-on, /${cmdPrefix}done-job, /${cmdPrefix}sync-linear`);
768
- }
769
657
  console.log("\nNext steps:");
770
658
  console.log(" 1. Set LINEAR_API_KEY in your shell profile:");
771
659
  console.log(` export LINEAR_API_KEY="${apiKey}"`);
772
660
  console.log(" 2. Run sync: ttt sync");
773
- if (commandsInstalled) {
774
- const cmdPrefix = commandPrefix ? `${commandPrefix}` : "";
775
- console.log(` 3. In Claude Code: /${cmdPrefix}work-on next`);
776
- console.log(`\n💡 Tip: Edit .claude/commands/${cmdPrefix}work-on.md to customize the "Verify" section for your project.`);
777
- }
778
- else {
779
- console.log(" 3. Start working: ttt work-on");
661
+ console.log(" 3. Start working: ttt work-on");
662
+ if (pluginInstructionsShown) {
663
+ console.log("\n💡 Tip: Install the Claude Code plugin for /ttt-* commands.");
780
664
  }
781
665
  }
782
666
  init().catch(console.error);
@@ -1,4 +1,4 @@
1
- import type { CompletionMode, Config, LocalConfig, QaPmTeamConfig, StatusTransitions, TeamConfig, UserConfig, LabelConfig } from "../utils.js";
1
+ import type { CompletionMode, Config, LabelConfig, LocalConfig, QaPmTeamConfig, StatusTransitions, TeamConfig, UserConfig } from "../utils.js";
2
2
  export interface LinearTeam {
3
3
  id: string;
4
4
  name: string;
@@ -1,11 +1,19 @@
1
1
  import type { LinearClient } from "@linear/sdk";
2
2
  import { type Config, type LocalConfig, type Task } from "../utils.js";
3
+ export interface FetchIssueOptions {
4
+ client?: LinearClient;
5
+ }
3
6
  export interface SyncIssueOptions {
4
7
  config: Config;
5
8
  localConfig: LocalConfig;
6
9
  client?: LinearClient;
7
10
  preserveLocalStatus?: boolean;
8
11
  }
12
+ /**
13
+ * Fetch issue details from Linear without saving to local data
14
+ * Returns Task object or null if issue not found
15
+ */
16
+ export declare function fetchIssueDetail(issueId: string, options?: FetchIssueOptions): Promise<Task | null>;
9
17
  /**
10
18
  * Sync a single issue from Linear and update local cycle data
11
19
  * Returns the updated task or null if issue not found
@@ -1,17 +1,15 @@
1
- import { getLinearClient, loadCycleData, saveCycleData, getPrioritySortIndex, } from "../utils.js";
1
+ import { getLinearClient, getPrioritySortIndex, loadCycleData, saveCycleData, } from "../utils.js";
2
2
  import { getStatusTransitions } from "./linear.js";
3
3
  /**
4
- * Sync a single issue from Linear and update local cycle data
5
- * Returns the updated task or null if issue not found
4
+ * Fetch issue details from Linear without saving to local data
5
+ * Returns Task object or null if issue not found
6
6
  */
7
- export async function syncSingleIssue(issueId, options) {
8
- const { config, localConfig: _localConfig, preserveLocalStatus = true, } = options;
7
+ export async function fetchIssueDetail(issueId, options = {}) {
9
8
  const client = options.client ?? getLinearClient();
10
9
  // Search for the issue
11
10
  const searchResult = await client.searchIssues(issueId);
12
11
  const matchingIssue = searchResult.nodes.find((i) => i.identifier === issueId);
13
12
  if (!matchingIssue) {
14
- console.error(`Issue ${issueId} not found in Linear.`);
15
13
  return null;
16
14
  }
17
15
  // Fetch full issue data
@@ -41,34 +39,12 @@ export async function syncSingleIssue(issueId, options) {
41
39
  user: user?.displayName ?? user?.email,
42
40
  };
43
41
  }));
44
- // Determine local status
45
- let localStatus = "pending";
46
- const existingData = await loadCycleData();
47
- if (preserveLocalStatus && existingData) {
48
- const existingTask = existingData.tasks.find((t) => t.id === issueId);
49
- if (existingTask) {
50
- localStatus = existingTask.localStatus;
51
- }
52
- }
53
- // Map remote status to local status if not preserving
54
- if (!preserveLocalStatus && state) {
55
- const transitions = getStatusTransitions(config);
56
- if (state.name === transitions.done) {
57
- localStatus = "completed";
58
- }
59
- else if (state.name === transitions.in_progress) {
60
- localStatus = "in-progress";
61
- }
62
- else {
63
- localStatus = "pending";
64
- }
65
- }
66
42
  const task = {
67
43
  id: issue.identifier,
68
44
  linearId: issue.id,
69
45
  title: issue.title,
70
46
  status: state ? state.name : "Unknown",
71
- localStatus: localStatus,
47
+ localStatus: "pending", // Default, will be overridden by sync if needed
72
48
  assignee: assigneeEmail,
73
49
  priority: issue.priority,
74
50
  labels: labelNames,
@@ -79,6 +55,42 @@ export async function syncSingleIssue(issueId, options) {
79
55
  attachments: attachments.length > 0 ? attachments : undefined,
80
56
  comments: comments.length > 0 ? comments : undefined,
81
57
  };
58
+ return task;
59
+ }
60
+ /**
61
+ * Sync a single issue from Linear and update local cycle data
62
+ * Returns the updated task or null if issue not found
63
+ */
64
+ export async function syncSingleIssue(issueId, options) {
65
+ const { config, localConfig: _localConfig, preserveLocalStatus = true, } = options;
66
+ const client = options.client ?? getLinearClient();
67
+ // Fetch issue details using shared function
68
+ const task = await fetchIssueDetail(issueId, { client });
69
+ if (!task) {
70
+ console.error(`Issue ${issueId} not found in Linear.`);
71
+ return null;
72
+ }
73
+ // Determine local status
74
+ const existingData = await loadCycleData();
75
+ if (preserveLocalStatus && existingData) {
76
+ const existingTask = existingData.tasks.find((t) => t.id === issueId);
77
+ if (existingTask) {
78
+ task.localStatus = existingTask.localStatus;
79
+ }
80
+ }
81
+ // Map remote status to local status if not preserving
82
+ if (!preserveLocalStatus) {
83
+ const transitions = getStatusTransitions(config);
84
+ if (task.status === transitions.done) {
85
+ task.localStatus = "completed";
86
+ }
87
+ else if (task.status === transitions.in_progress) {
88
+ task.localStatus = "in-progress";
89
+ }
90
+ else {
91
+ task.localStatus = "pending";
92
+ }
93
+ }
82
94
  // Update cycle data
83
95
  if (existingData) {
84
96
  const existingTasks = existingData.tasks.filter((t) => t.id !== issueId);
@@ -1,5 +1,5 @@
1
- import { getLinearClient, getPaths, getPrioritySortIndex, getTeamId, loadConfig, loadCycleData, loadLocalConfig, saveConfig, saveCycleData, } from "./utils.js";
2
1
  import { clearIssueImages, downloadLinearImage, ensureOutputDir, extractLinearImageUrls, isLinearImageUrl, } from "./lib/images.js";
2
+ import { getLinearClient, getPaths, getPrioritySortIndex, getTeamId, loadConfig, loadCycleData, loadLocalConfig, saveConfig, saveCycleData, } from "./utils.js";
3
3
  async function sync() {
4
4
  const args = process.argv.slice(2);
5
5
  // Handle help flag
@@ -1,5 +1,5 @@
1
1
  import prompts from "prompts";
2
- import { PRIORITY_LABELS, displayTaskFull } from "./lib/display.js";
2
+ import { displayTaskFull, PRIORITY_LABELS } from "./lib/display.js";
3
3
  import { getStatusTransitions, updateIssueStatus } from "./lib/linear.js";
4
4
  import { getPrioritySortIndex, loadConfig, loadCycleData, loadLocalConfig, saveCycleData, } from "./utils.js";
5
5
  async function workOn() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "team-toon-tack",
3
- "version": "2.1.0",
3
+ "version": "2.3.0",
4
4
  "description": "Linear task sync & management CLI with TOON format",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,12 +13,14 @@
13
13
  },
14
14
  "files": [
15
15
  "dist",
16
- "templates"
16
+ ".claude-plugin",
17
+ "commands",
18
+ "skills"
17
19
  ],
18
20
  "scripts": {
19
21
  "build": "tsc",
20
22
  "lint": "biome lint .",
21
- "format": "biome format --write .",
23
+ "format": "biome check --write .",
22
24
  "type": "tsc --noEmit",
23
25
  "prepublishOnly": "npm run build",
24
26
  "release": "npm config set //registry.npmjs.org/:_authToken=$NPM_PUBLISH_KEY && npm publish"
@@ -0,0 +1,170 @@
1
+ ---
2
+ name: linear-task-manager
3
+ description: Linear task management expert using ttt CLI. Manages task workflow, syncs issues, tracks status. Use when working with Linear issues, starting tasks, completing work, or checking task status.
4
+ ---
5
+
6
+ # Linear Task Manager
7
+
8
+ You are a Linear task management expert using the team-toon-tack (ttt) CLI tool.
9
+
10
+ ## Your Role
11
+
12
+ Help developers efficiently manage their Linear workflow:
13
+ - Sync issues from Linear to local cache
14
+ - Start working on tasks
15
+ - Track and update task status
16
+ - Complete tasks with proper documentation
17
+ - Fetch issue details on demand
18
+
19
+ ## Prerequisites
20
+
21
+ Ensure the project has:
22
+ 1. `LINEAR_API_KEY` environment variable set
23
+ 2. `.ttt/` directory initialized (run `ttt init` if not)
24
+ 3. `ttt` CLI installed (`npm install -g team-toon-tack`)
25
+
26
+ ## Core Workflows
27
+
28
+ ### 1. Starting a Work Session
29
+
30
+ ```bash
31
+ # Sync latest issues from Linear
32
+ ttt sync
33
+
34
+ # Pick a task to work on (interactive or auto-select)
35
+ ttt work-on next
36
+ # or
37
+ ttt work-on MP-624
38
+ ```
39
+
40
+ ### 2. During Development
41
+
42
+ ```bash
43
+ # Check current task status
44
+ ttt status
45
+
46
+ # Get full issue details
47
+ ttt get-issue MP-624
48
+
49
+ # Mark task as blocked if waiting on dependency
50
+ ttt status MP-624 --set blocked
51
+ ```
52
+
53
+ ### 3. Completing Work
54
+
55
+ ```bash
56
+ # Ensure code is committed first
57
+ git add . && git commit -m "feat: implement feature"
58
+
59
+ # Mark task as done with message
60
+ ttt done -m "Implemented feature with full test coverage"
61
+ ```
62
+
63
+ ### 4. Syncing Changes
64
+
65
+ ```bash
66
+ # Pull latest from Linear
67
+ ttt sync
68
+
69
+ # Push local status changes to Linear (if using local mode)
70
+ ttt sync --update
71
+ ```
72
+
73
+ ## Status Flow
74
+
75
+ ```
76
+ pending → in-progress → completed
77
+ ↓
78
+ blocked
79
+ ```
80
+
81
+ ### Local Status vs Linear Status
82
+
83
+ | Local Status | Linear Status |
84
+ |--------------|---------------|
85
+ | pending | Todo |
86
+ | in-progress | In Progress |
87
+ | completed | Done / Testing |
88
+ | blocked | (configurable) |
89
+
90
+ ## Completion Modes
91
+
92
+ The `ttt done` command behaves differently based on configured mode:
93
+
94
+ | Mode | Task Action | Parent Action |
95
+ |------|-------------|---------------|
96
+ | `simple` | → Done | → Done |
97
+ | `strict_review` | → Testing | → QA Testing |
98
+ | `upstream_strict` | → Done | → Testing |
99
+ | `upstream_not_strict` | → Done | → Testing (no fallback) |
100
+
101
+ ## File Structure
102
+
103
+ ```
104
+ .ttt/
105
+ ├── config.toon # Team configuration
106
+ ├── local.toon # Personal settings
107
+ ├── cycle.toon # Current cycle tasks (auto-generated)
108
+ └── output/ # Downloaded attachments
109
+ ```
110
+
111
+ ## Best Practices
112
+
113
+ ### DO
114
+ - Always `ttt sync` before starting work
115
+ - Use `ttt work-on next` for auto-prioritization
116
+ - Include meaningful messages with `ttt done -m "..."`
117
+ - Check `ttt status` to verify state before commits
118
+
119
+ ### DON'T
120
+ - Don't manually edit `cycle.toon` - use CLI commands
121
+ - Don't skip sync - local data may be stale
122
+ - Don't forget to commit before `ttt done`
123
+
124
+ ## Troubleshooting
125
+
126
+ ### "No cycle data found"
127
+ Run `ttt sync` to fetch issues from Linear.
128
+
129
+ ### "Issue not found in current cycle"
130
+ The issue may not match filters. Check:
131
+ - Issue is in active cycle
132
+ - Issue status is Todo or In Progress
133
+ - Issue matches configured label filter
134
+
135
+ ### "LINEAR_API_KEY not set"
136
+ ```bash
137
+ export LINEAR_API_KEY="lin_api_xxxxx"
138
+ ```
139
+
140
+ ## Examples
141
+
142
+ ### Example: Start Daily Work
143
+ ```bash
144
+ ttt sync # Get latest issues
145
+ ttt work-on next # Auto-select highest priority
146
+ # Read task details displayed
147
+ git checkout -b feature/mp-624-new-feature
148
+ # Start coding...
149
+ ```
150
+
151
+ ### Example: Complete and Move On
152
+ ```bash
153
+ git add . && git commit -m "feat: add new feature"
154
+ ttt done -m "Added feature with tests"
155
+ ttt work-on next # Move to next task
156
+ ```
157
+
158
+ ### Example: Check Specific Issue
159
+ ```bash
160
+ ttt get-issue MP-624 # Fetch from Linear
161
+ ttt get-issue MP-624 --local # Show cached data
162
+ ```
163
+
164
+ ## Important Rules
165
+
166
+ - Always verify `LINEAR_API_KEY` is set before operations
167
+ - Run `ttt sync` at the start of each work session
168
+ - Commit code before running `ttt done`
169
+ - Use `--local` flag to avoid API calls when checking cached data
170
+ - Check `.ttt/output/` for downloaded attachments and images
@@ -1,45 +0,0 @@
1
- ---
2
- name: done-job
3
- description: Mark a Linear issue as done with AI summary comment
4
- arguments:
5
- - name: issue-id
6
- description: Linear issue ID (e.g., MP-624). Optional if only one task is in-progress
7
- required: false
8
- ---
9
-
10
- # Complete Task
11
-
12
- Mark a task as done and update Linear with commit details.
13
-
14
- ## Process
15
-
16
- ### 1. Determine Issue ID
17
-
18
- Check `.toon/cycle.toon` for tasks with `localStatus: in-progress`.
19
-
20
- ### 2. Write Fix Summary
21
-
22
- Prepare a concise summary (1-3 sentences) covering:
23
- - Root cause
24
- - How it was resolved
25
- - Key code changes
26
-
27
- ### 3. Run Command
28
-
29
- ```bash
30
- ttt done -d .ttt $ARGUMENTS -m "äŋŽåžŠčĒĒæ˜Ž"
31
- ```
32
-
33
- ## What It Does
34
-
35
- - Linear issue status → "Done"
36
- - Adds comment with commit hash, message, and diff summary
37
- - Parent issue (if exists) → "Testing"
38
- - Local status → `completed` in `.toon/cycle.toon`
39
-
40
- ## Example Usage
41
-
42
- ```
43
- /done-job MP-624
44
- /done-job
45
- ```
@@ -1,32 +0,0 @@
1
- ---
2
- name: sync-linear
3
- description: Sync Linear Frontend issues to local TOON file
4
- ---
5
-
6
- # Sync Linear Issues
7
-
8
- Fetch current cycle's Frontend issues from Linear to `.toon/cycle.toon`.
9
-
10
- ## Process
11
-
12
- ### 1. Run Sync
13
-
14
- ```bash
15
- ttt sync -d .ttt
16
- ```
17
-
18
- ### 2. Review Output
19
-
20
- Script displays a summary of tasks in the current cycle.
21
-
22
- ## When to Use
23
-
24
- - Before starting a new work session
25
- - When task list is missing or outdated
26
- - After issues are updated in Linear
27
-
28
- ## Example Usage
29
-
30
- ```
31
- /sync-linear
32
- ```