takomi 2.1.32 → 2.1.34

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 (54) hide show
  1. package/.pi/extensions/oauth-router/config.ts +14 -5
  2. package/.pi/extensions/oauth-router/index.ts +130 -130
  3. package/.pi/extensions/oauth-router/provider.ts +29 -0
  4. package/.pi/extensions/oauth-router/state.ts +372 -372
  5. package/.pi/extensions/oauth-router/types.ts +1 -1
  6. package/.pi/extensions/takomi-runtime/command-text.ts +2 -4
  7. package/.pi/extensions/takomi-runtime/commands.ts +15 -21
  8. package/.pi/extensions/takomi-runtime/index.ts +127 -53
  9. package/.pi/extensions/takomi-runtime/model-routing-defaults.ts +296 -296
  10. package/.pi/extensions/takomi-runtime/ui.ts +18 -11
  11. package/.pi/extensions/takomi-subagents/index.ts +2 -0
  12. package/.pi/extensions/takomi-subagents/native-render.ts +27 -5
  13. package/.pi/extensions/takomi-subagents/pi-subagents-engine.ts +1 -1
  14. package/.pi/extensions/takomi-subagents/tool-runner.ts +1 -0
  15. package/assets/.agent/skills/photo-book-builder/SKILL.md +96 -0
  16. package/assets/.agent/skills/photo-book-builder/references/layout_templates.md +72 -0
  17. package/assets/.agent/skills/photo-book-builder/scripts/create_full_bleed_layouts.py +212 -0
  18. package/assets/.agent/skills/photo-book-builder/scripts/organize_photos.py +99 -0
  19. package/assets/.agent/skills/photo-book-builder/scripts/revert_organization.py +61 -0
  20. package/assets/.agent/skills/photo-book-builder/scripts/upscale_covers.py +47 -0
  21. package/assets/.agent/skills/youtube-pipeline/SKILL.md +73 -62
  22. package/assets/.agent/skills/youtube-pipeline/resources/knowledge/Application.md +1 -0
  23. package/assets/.agent/skills/youtube-pipeline/resources/knowledge/Phase 1.md +86 -0
  24. package/assets/.agent/skills/youtube-pipeline/resources/knowledge/Phase 2.md +106 -0
  25. package/assets/.agent/skills/youtube-pipeline/resources/knowledge/Phase 3.md +112 -0
  26. package/assets/.agent/skills/youtube-pipeline/resources/knowledge/Phase 4.md +90 -0
  27. package/assets/.agent/skills/youtube-pipeline/resources/knowledge/Phased Outline.md +58 -0
  28. package/assets/.agent/skills/youtube-pipeline/resources/knowledge/Repurposing.md +1 -0
  29. package/assets/.agent/skills/youtube-pipeline/resources/knowledge/Research.md +438 -0
  30. package/assets/.agent/skills/youtube-pipeline/resources/prompts/Shorts Bridge Protocol.md +159 -0
  31. package/assets/.agent/skills/youtube-pipeline/resources/prompts/Title Thumbnail Picker Prompt.md +144 -0
  32. package/assets/.agent/skills/youtube-pipeline/resources/prompts/Transcription Extraction Prompt v2.md +190 -0
  33. package/assets/.agent/skills/youtube-pipeline/resources/prompts/Transcription Extraction Prompt.md +156 -0
  34. package/assets/.agent/skills/youtube-pipeline/resources/prompts/Video QA Prompt.md +133 -0
  35. package/assets/.agent/skills/youtube-pipeline/resources/youtube-phase1-strategy.md +28 -18
  36. package/assets/.agent/skills/youtube-pipeline/resources/youtube-phase2-packaging.md +2 -2
  37. package/assets/.agent/skills/youtube-pipeline/resources/youtube-phase3-scripting.md +2 -2
  38. package/assets/.agent/skills/youtube-pipeline/resources/youtube-phase3.5-shorts.md +2 -2
  39. package/assets/.agent/skills/youtube-pipeline/resources/youtube-phase4-production.md +2 -2
  40. package/assets/.agent/skills/youtube-pipeline/resources/youtube-pipeline.md +15 -15
  41. package/assets/.agent/skills/youtube-pipeline/scripts/google-trends/package.json +17 -0
  42. package/assets/.agent/skills/youtube-pipeline/scripts/google-trends/pnpm-lock.yaml +31 -0
  43. package/assets/.agent/skills/youtube-pipeline/scripts/google-trends/search.js +168 -0
  44. package/package.json +1 -1
  45. package/src/cli.js +13 -4
  46. package/src/pi-harness.js +36 -14
  47. package/src/pi-optional-features.js +190 -190
  48. package/src/postinstall.js +27 -27
  49. package/src/skills-catalog.js +245 -245
  50. package/src/skills-installer.js +244 -244
  51. package/src/skills-selection-tui.js +200 -200
  52. package/src/store.js +418 -418
  53. package/src/takomi-stats.d.ts +3 -3
  54. package/src/takomi-stats.js +442 -35
@@ -0,0 +1,133 @@
1
+ **You are "QA Hawk" — a ruthless YouTube video quality auditor.**
2
+
3
+ Your job is to watch my video (or the intro section I provide) and tear it apart before my audience does. You are not here to be nice. You are here to catch every weakness, every boring moment, every missed opportunity.
4
+
5
+ ---
6
+
7
+ ### **WHAT I WILL PROVIDE:**
8
+
9
+ I will give you one of the following:
10
+ - **Full video file** (or link)
11
+ - **Intro clip only** (first 30-60 seconds)
12
+ - **Key timestamps to review**
13
+ - **Screenshots at specific moments**
14
+
15
+ I may also provide:
16
+ - The **title and thumbnail** (for consistency check)
17
+ - The **script** (to compare intent vs. execution)
18
+
19
+ ---
20
+
21
+ ### **YOUR FRAMEWORK: THE 5 AUDITS**
22
+
23
+ Run the video through these 5 audits and report issues for each.
24
+
25
+ ---
26
+
27
+ ## **1. THE HOOK AUDIT (0:00 - 0:45)**
28
+ *Reference: Phase 3 Hook Structure*
29
+
30
+ | Check | Pass/Fail | Notes |
31
+ |-------|-----------|-------|
32
+ | **First Frame Match** — Does the first frame match the thumbnail? | | |
33
+ | **Scroll Stopper** — Is the first line compelling enough to stop a scroll? | | |
34
+ | **Stakes Clear** — Do I know what I lose by leaving within 10 seconds? | | |
35
+ | **Input Bias** — Is there a credibility flex ("I spent X doing Y")? | | |
36
+ | **Payoff Promise** — Do I know what I'll get by the end? | | |
37
+ | **No Wasted Time** — Is there any rambling, logos, or "hey guys" before the hook? | | |
38
+
39
+ **The 5-Second Test:** If I was scrolling YouTube, would I stop on this? Why or why not?
40
+
41
+ ---
42
+
43
+ ## **2. THE RETENTION AUDIT (Full Video)**
44
+ *Reference: Phase 3 Loop Architecture + Phase 4 Dopamine Machine*
45
+
46
+ | Check | Pass/Fail | Notes |
47
+ |-------|-----------|-------|
48
+ | **Screen Change Frequency** — Does the visual change every 3-5 seconds? | | |
49
+ | **Pattern Interrupts** — Is there a drastic change every 45-60 seconds? | | |
50
+ | **Open Loops** — Are there forward hooks that make me want to keep watching? | | |
51
+ | **Dead Air** — Are there any gaps, pauses, or boring stretches? | | |
52
+ | **Mid-Video Dip** — Is there a section where I would click away? Mark the timestamp. | | |
53
+ | **Pacing** — Does it feel too slow, too rushed, or just right? | | |
54
+
55
+ **The Boredom Timestamp:** At what exact moment did my attention first wander? Why?
56
+
57
+ ---
58
+
59
+ ## **3. THE VISUAL AUDIT**
60
+ *Reference: Phase 4 Filming Protocol + Dopamine Machine*
61
+
62
+ | Check | Pass/Fail | Notes |
63
+ |-------|-----------|-------|
64
+ | **Lighting** — Is the face well-lit without harsh shadows? | | |
65
+ | **Audio** — Is it clean, clear, and close? Any echo or distortion? | | |
66
+ | **Eye Contact** — Does the speaker maintain lens lock? | | |
67
+ | **Energy** — Is the delivery 110% or does it feel flat? | | |
68
+ | **B-Roll Quality** — Is the B-roll relevant and high quality? | | |
69
+ | **Text/Graphics** — Are they clean, readable, and not overwhelming? | | |
70
+ | **Thumbnail Consistency** — Does the video match the thumbnail promise? | | |
71
+
72
+ ---
73
+
74
+ ## **4. THE TITLE/THUMBNAIL SYNC AUDIT**
75
+ *Reference: Phase 2 Synergy Check*
76
+
77
+ | Check | Pass/Fail | Notes |
78
+ |-------|-----------|-------|
79
+ | **Title Delivered** — Does the video actually deliver on the title promise? | | |
80
+ | **Thumbnail Payoff** — Is the thumbnail moment in the video? | | |
81
+ | **No Bait-and-Switch** — Would a viewer feel misled? | | |
82
+ | **Curiosity Closed** — Is the curiosity gap from the title fully answered? | | |
83
+
84
+ ---
85
+
86
+ ## **5. THE OUTRO AUDIT**
87
+ *Reference: Phase 3 Outro Strategy*
88
+
89
+ | Check | Pass/Fail | Notes |
90
+ |-------|-----------|-------|
91
+ | **No Signal Words** — Did I say "in conclusion," "that's it," or "thanks for watching"? | | |
92
+ | **Bridge to Next Video** — Is there a clear CTA to a specific next video? | | |
93
+ | **Open Loop Forward** — Does the outro create curiosity for the next video? | | |
94
+ | **Hard vs. Soft CTA** — Which was used and was it appropriate? | | |
95
+
96
+ ---
97
+
98
+ ### **OUTPUT FORMAT**
99
+
100
+ After auditing, provide:
101
+
102
+ ```
103
+ 🔴 CRITICAL ISSUES (Fix before upload)
104
+ - [Issue 1]
105
+ - [Issue 2]
106
+
107
+ 🟡 WARNINGS (Should fix, but not fatal)
108
+ - [Issue 1]
109
+ - [Issue 2]
110
+
111
+ 🟢 WINS (What's working well)
112
+ - [Strength 1]
113
+ - [Strength 2]
114
+
115
+ 📍 BOREDOM TIMESTAMPS
116
+ - [Timestamp 1]: [Why attention dropped]
117
+ - [Timestamp 2]: [Why attention dropped]
118
+
119
+ 🎯 FINAL VERDICT
120
+ [SHIP IT / NEEDS WORK / DO NOT UPLOAD]
121
+
122
+ Reason: [One sentence summary]
123
+ ```
124
+
125
+ ---
126
+
127
+ ### **ATTITUDE REMINDER**
128
+
129
+ You are not my friend. You are my harshest critic. If the video is mid, say it's mid. If the intro is boring, say it's boring. If the hook is weak, roast it.
130
+
131
+ Better I hear it from you than from the comments section.
132
+
133
+ **NOW PROVIDE THE VIDEO/CLIP TO AUDIT:**
@@ -7,9 +7,9 @@ description: Phase 1 of YouTube Pipeline - The Strategy Engine (Ideation & Resea
7
7
  > **Your Role**: You are a brutal expert YouTube strategist. You generate ideas, challenge weak concepts, and demand proof. You teach the "why" behind every step. Never yes-man.
8
8
 
9
9
  ## Step 0: Load Source Knowledge
10
- Before starting, read the full phase document to get undiluted context:
10
+ Before starting, read the full phase document to get undiluted context (packaged locally):
11
11
  ```
12
- View file: c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\📂 Processed_Notes\Workflow\Phase 1.md
12
+ View file: knowledge/Phase 1.md
13
13
  ```
14
14
 
15
15
  ## Step 1: Gather Context
@@ -19,7 +19,7 @@ Ask the user:
19
19
  3. **Target Audience**: "Who exactly watches you? Age, situation, pain points?"
20
20
  4. **Mode**: "Do you want me to drive (Guided) or do you want more control (Manual)?"
21
21
 
22
- If user has prior notes/summaries in the vault, reference them to pre-fill answers.
22
+ If the user provides prior notes, summaries, or project context, use them to pre-fill answers. Do not depend on a private vault path.
23
23
 
24
24
  ## Step 2: The Outlier Hunt (AI-Driven)
25
25
  Based on their niche, **you generate** potential outlier directions:
@@ -67,10 +67,11 @@ Guide the user through this process to extract bulk data:
67
67
  4. **User Action**: Right-click → Copy → Copy outerHTML
68
68
  5. **User Action**: Paste into a `.html` file (e.g., `ai_coding.html`)
69
69
  6. **Agent Action**: Parse the file:
70
- ```powershell
71
- # Parse YouTube Studio HTML export
72
- powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.gemini\antigravity\skills\youtube-pipeline\scripts\parse_yt_studio.ps1" -InputFile "ai_coding.html" -OutputFile "parsed_topics.md"
73
- ```
70
+ ```powershell
71
+ # Parse YouTube Studio HTML export
72
+ $SkillRoot = "<path-to-installed-youtube-pipeline-skill>"
73
+ powershell -ExecutionPolicy Bypass -File (Join-Path $SkillRoot "scripts/parse_yt_studio.ps1") -InputFile "ai_coding.html" -OutputFile "parsed_topics.md"
74
+ ```
74
75
 
75
76
  **Repeat for each topic category** (e.g., "Claude AI", "VibeCoding", "Design System") to build comprehensive demand data.
76
77
 
@@ -118,17 +119,26 @@ Ask them to go to their top 3 outlier videos and pull:
118
119
  ### 4b. Google Trends Deep Dive
119
120
  Don't just glance at a trend line. Use Google Trends properly:
120
121
 
121
- **⚡ AUTOMATED (Agent Use - Preferred):**
122
- Use the `google-trends` skill for CLI-based searching:
123
- ```powershell
124
- # Search YouTube trends for a keyword
125
- node "$env:USERPROFILE\.gemini\antigravity\skills\google-trends\scripts\search.js" -k "Claude Cowork" -p youtube -t "now 7-d" -o table
126
-
127
- # Search multiple keywords
128
- node "$env:USERPROFILE\.gemini\antigravity\skills\google-trends\scripts\search.js" -k "Vibe Coding" -p youtube
129
- node "$env:USERPROFILE\.gemini\antigravity\skills\google-trends\scripts\search.js" -k "AI coding" -p youtube
130
- node "$env:USERPROFILE\.gemini\antigravity\skills\google-trends\scripts\search.js" -k "Cursor IDE" -p youtube
131
- ```
122
+ **Automated Method (Bundled CLI):**
123
+ Use the packaged Google Trends CLI in this skill:
124
+ ```powershell
125
+ # First-time dependency install
126
+ $SkillRoot = "<path-to-installed-youtube-pipeline-skill>"
127
+ $TrendRoot = Join-Path $SkillRoot "scripts/google-trends"
128
+ Push-Location $TrendRoot
129
+ pnpm install
130
+ Pop-Location
131
+
132
+ # Search YouTube trends for a keyword
133
+ node (Join-Path $SkillRoot "scripts/google-trends/search.js") -k "Claude Cowork" -p youtube -t "now 7-d" -o table
134
+
135
+ # Search multiple keywords
136
+ node (Join-Path $SkillRoot "scripts/google-trends/search.js") -k "Vibe Coding" -p youtube
137
+ node (Join-Path $SkillRoot "scripts/google-trends/search.js") -k "AI coding" -p youtube
138
+ node (Join-Path $SkillRoot "scripts/google-trends/search.js") -k "Cursor IDE" -p youtube
139
+ ```
140
+
141
+ Do not assume a specific install root such as `~/.gemini`, `~/.codex`, `~/.agents`, or any private project folder. If Node dependencies are unavailable, use the manual method below.
132
142
 
133
143
  **Key Signals:**
134
144
  - `BREAKOUT` = 5000%+ growth = **GOLD**
@@ -7,9 +7,9 @@ description: Phase 2 of YouTube Pipeline - The Packaging Lab (Title & Thumbnail)
7
7
  > **Your Role**: You are a brutal expert YouTube strategist. You generate titles and thumbnail concepts. You critique ruthlessly. The packaging MUST be irresistible before we move to scripting.
8
8
 
9
9
  ## Step 0: Load Source Knowledge
10
- Before starting, read the full phase document:
10
+ Before starting, read the full phase document (packaged locally):
11
11
  ```
12
- View file: c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\📂 Processed_Notes\Workflow\Phase 2.md
12
+ View file: knowledge/Phase 2.md
13
13
  ```
14
14
 
15
15
  Also recall the Phase 1 output:
@@ -7,9 +7,9 @@ description: Phase 3 of YouTube Pipeline - The Scripting Forge (Retention & Psyc
7
7
  > **Your Role**: You are a brutal expert YouTube scriptwriter. You draft hooks, structure loops, and write copy. Every sentence must build tension, provide value, or move the story forward. If it does neither, delete it.
8
8
 
9
9
  ## Step 0: Load Source Knowledge
10
- Before starting, read the full phase document:
10
+ Before starting, read the full phase document (packaged locally):
11
11
  ```
12
- View file: c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\📂 Processed_Notes\Workflow\Phase 3.md
12
+ View file: knowledge/Phase 3.md
13
13
  ```
14
14
 
15
15
  Also recall Phase 1 & 2 outputs:
@@ -16,9 +16,9 @@ Run this **after Phase 3 (Scripting)** is complete, or during Phase 3 if you wan
16
16
 
17
17
  ## Step 0: Load Source Knowledge
18
18
 
19
- Read the Phase 3 source document to get the full scripting framework:
19
+ Read the Phase 3 source document to get the full scripting framework (packaged locally):
20
20
  ```
21
- View file: c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\📂 Processed_Notes\Workflow\Phase 3.md
21
+ View file: knowledge/Phase 3.md
22
22
  ```
23
23
 
24
24
  This gives you access to:
@@ -7,9 +7,9 @@ description: Phase 4 of YouTube Pipeline - Production & Post-Production. Film, e
7
7
  > **Your Role**: You are a brutal expert video producer. You create filming checklists, editing guides, and quality control passes. The script provides value; the edit provides dopamine.
8
8
 
9
9
  ## Step 0: Load Source Knowledge
10
- Before starting, read the full phase document:
10
+ Before starting, read the full phase document (packaged locally):
11
11
  ```
12
- View file: c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\📂 Processed_Notes\Workflow\Phase 4.md
12
+ View file: knowledge/Phase 4.md
13
13
  ```
14
14
 
15
15
  Also recall all previous outputs:
@@ -124,21 +124,21 @@ Status: FULLY DISTRIBUTED
124
124
  ---
125
125
 
126
126
  ## Phase Workflow References
127
- Each phase has its own detailed workflow:
128
- - Phase 1: `c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\.agent\workflows\youtube-phase1-strategy.md`
129
- - Phase 2: `c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\.agent\workflows\youtube-phase2-packaging.md`
130
- - Phase 3: `c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\.agent\workflows\youtube-phase3-scripting.md`
131
- - Phase 3.5: `c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\.agent\workflows\youtube-phase3.5-shorts.md`
132
- - Phase 4: `c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\.agent\workflows\youtube-phase4-production.md`
133
- - Phase 5: `c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\.agent\workflows\youtube-phase5-repurposing.md`
134
-
135
- Each workflow also reads from source knowledge:
136
- - Source 1: `c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\📂 Processed_Notes\Workflow\Phase 1.md`
137
- - Source 2: `c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\📂 Processed_Notes\Workflow\Phase 2.md`
138
- - Source 3: `c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\📂 Processed_Notes\Workflow\Phase 3.md`
139
- - Source 4: `c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\📂 Processed_Notes\Workflow\Phase 4.md`
140
- - Research: `c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\📂 Processed_Notes\Workflow\Research.md`
141
- - Repurposing: `c:\CreativeOS\Creator_Command_Hub_Obsidian\📁 YouTube Brain\📂 Processed_Notes\Workflow\Repurposing.md`
127
+ Each phase has its own detailed workflow (packaged locally):
128
+ - Phase 1: `youtube-phase1-strategy.md`
129
+ - Phase 2: `youtube-phase2-packaging.md`
130
+ - Phase 3: `youtube-phase3-scripting.md`
131
+ - Phase 3.5: `youtube-phase3.5-shorts.md`
132
+ - Phase 4: `youtube-phase4-production.md`
133
+ - Phase 5: `youtube-phase5-repurposing.md`
134
+
135
+ Each workflow also reads from local source knowledge:
136
+ - Source 1: `knowledge/Phase 1.md`
137
+ - Source 2: `knowledge/Phase 2.md`
138
+ - Source 3: `knowledge/Phase 3.md`
139
+ - Source 4: `knowledge/Phase 4.md`
140
+ - Research: `knowledge/Research.md`
141
+ - Repurposing: `knowledge/Repurposing.md`
142
142
 
143
143
  ---
144
144
 
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "google-trends-cli",
3
+ "version": "1.0.0",
4
+ "description": "CLI for Google Trends research automation",
5
+ "main": "search.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "search": "node search.js"
9
+ },
10
+ "keywords": ["google-trends", "youtube", "research"],
11
+ "author": "J STAR FILMS",
12
+ "license": "MIT",
13
+ "dependencies": {
14
+ "commander": "^12.0.0",
15
+ "google-trends-api": "^4.9.2"
16
+ }
17
+ }
@@ -0,0 +1,31 @@
1
+ lockfileVersion: '9.0'
2
+
3
+ settings:
4
+ autoInstallPeers: true
5
+ excludeLinksFromLockfile: false
6
+
7
+ importers:
8
+
9
+ .:
10
+ dependencies:
11
+ commander:
12
+ specifier: ^12.0.0
13
+ version: 12.1.0
14
+ google-trends-api:
15
+ specifier: ^4.9.2
16
+ version: 4.9.2
17
+
18
+ packages:
19
+
20
+ commander@12.1.0:
21
+ resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
22
+ engines: {node: '>=18'}
23
+
24
+ google-trends-api@4.9.2:
25
+ resolution: {integrity: sha512-gjVSHCM8B7LyAAUpXb4B0/TfnmpwQ2z1w/mQ2bL0AKpr2j3gLS1j2YOnifpfsGJRxAGXB/NoC+nGwC5qSnZIiA==}
26
+
27
+ snapshots:
28
+
29
+ commander@12.1.0: {}
30
+
31
+ google-trends-api@4.9.2: {}
@@ -0,0 +1,168 @@
1
+ #!/usr/bin/env node
2
+ import { program } from 'commander';
3
+ import googleTrends from 'google-trends-api';
4
+
5
+ program
6
+ .name('search')
7
+ .description('Google Trends CLI for topic research')
8
+ .requiredOption('-k, --keyword <string>', 'Topic to search')
9
+ .option('-p, --property <string>', 'youtube | web | images | news | froogle', 'youtube')
10
+ .option('-t, --time <string>', 'Time range (now 7-d, now 1-m, today 3-m, today 12-m)', 'now 7-d')
11
+ .option('-c, --category <number>', 'Category ID (5 = Tech)', '5')
12
+ .option('-o, --output <string>', 'Output format: table | json | markdown', 'table')
13
+ .option('-f, --file <path>', 'Output file path')
14
+ .option('--interest', 'Include interest-over-time data', false)
15
+ .parse();
16
+
17
+ const opts = program.opts();
18
+
19
+ // Parse time range string to date
20
+ function getStartTime(timeStr) {
21
+ const now = Date.now();
22
+ const match = timeStr.match(/^(now|today)\s+(\d+)-([dmy])$/);
23
+ if (!match) return new Date(now - 7 * 24 * 60 * 60 * 1000); // default 7 days
24
+
25
+ const [, , num, unit] = match;
26
+ const amount = parseInt(num, 10);
27
+ switch (unit) {
28
+ case 'd': return new Date(now - amount * 24 * 60 * 60 * 1000);
29
+ case 'm': return new Date(now - amount * 30 * 24 * 60 * 60 * 1000);
30
+ case 'y': return new Date(now - amount * 365 * 24 * 60 * 60 * 1000);
31
+ default: return new Date(now - 7 * 24 * 60 * 60 * 1000);
32
+ }
33
+ }
34
+
35
+ async function fetchRelatedQueries() {
36
+ const result = await googleTrends.relatedQueries({
37
+ keyword: opts.keyword,
38
+ startTime: getStartTime(opts.time),
39
+ property: opts.property === 'web' ? '' : opts.property,
40
+ category: parseInt(opts.category, 10),
41
+ });
42
+ return JSON.parse(result);
43
+ }
44
+
45
+ async function fetchInterestOverTime() {
46
+ if (!opts.interest) return null;
47
+ const result = await googleTrends.interestOverTime({
48
+ keyword: opts.keyword,
49
+ startTime: getStartTime(opts.time),
50
+ property: opts.property === 'web' ? '' : opts.property,
51
+ category: parseInt(opts.category, 10),
52
+ });
53
+ return JSON.parse(result);
54
+ }
55
+
56
+ function formatTable(data, interest) {
57
+ const lines = [];
58
+ lines.push(`\n[TrendProbe] Searching: "${opts.keyword}" on ${opts.property} (${opts.time})\n`);
59
+
60
+ const ranked = data?.default?.rankedList || [];
61
+ ranked.forEach((list, idx) => {
62
+ const label = idx === 0 ? 'Top' : 'Rising';
63
+ lines.push(`--- Related Queries (${label}) ---`);
64
+
65
+ (list.rankedKeyword || []).forEach((item, i) => {
66
+ const value = typeof item.value === 'string' ? item.value : item.value;
67
+ const display = item.formattedValue || (value === 'Breakout' ? 'BREAKOUT' : value);
68
+ lines.push(`${i + 1}. ${item.query} (${display})`);
69
+ });
70
+ lines.push('');
71
+ });
72
+
73
+ if (interest?.default?.timelineData) {
74
+ lines.push('--- Interest Over Time ---');
75
+ const timeline = interest.default.timelineData.slice(-7); // Last 7 data points
76
+ timeline.forEach(point => {
77
+ lines.push(`${point.formattedTime}: ${point.value[0]}`);
78
+ });
79
+ lines.push('');
80
+ }
81
+
82
+ return lines.join('\n');
83
+ }
84
+
85
+ function formatJSON(data, interest) {
86
+ const ranked = data?.default?.rankedList || [];
87
+ const result = {
88
+ keyword: opts.keyword,
89
+ property: opts.property,
90
+ time: opts.time,
91
+ category: opts.category,
92
+ top: (ranked[0]?.rankedKeyword || []).map(q => ({ query: q.query, value: q.value })),
93
+ rising: (ranked[1]?.rankedKeyword || []).map(q => ({ query: q.query, value: q.formattedValue || q.value })),
94
+ };
95
+ if (interest?.default?.timelineData) {
96
+ result.interest = interest.default.timelineData.map(p => ({ time: p.formattedTime, value: p.value[0] }));
97
+ }
98
+ return JSON.stringify(result, null, 2);
99
+ }
100
+
101
+ function formatMarkdown(data, interest) {
102
+ const lines = [];
103
+ lines.push(`## ${opts.keyword} (${opts.property}, ${opts.time})`);
104
+ lines.push('');
105
+
106
+ const ranked = data?.default?.rankedList || [];
107
+ if (ranked[0]?.rankedKeyword?.length) {
108
+ lines.push('### Top Queries');
109
+ ranked[0].rankedKeyword.forEach((q, i) => {
110
+ lines.push(`${i + 1}. ${q.query} (${q.value})`);
111
+ });
112
+ lines.push('');
113
+ }
114
+
115
+ if (ranked[1]?.rankedKeyword?.length) {
116
+ lines.push('### Rising Queries');
117
+ ranked[1].rankedKeyword.forEach((q, i) => {
118
+ const display = q.formattedValue || q.value;
119
+ lines.push(`${i + 1}. ${q.query} (${display})`);
120
+ });
121
+ lines.push('');
122
+ }
123
+
124
+ if (interest?.default?.timelineData) {
125
+ lines.push('### Interest Over Time');
126
+ interest.default.timelineData.slice(-7).forEach(p => {
127
+ lines.push(`- ${p.formattedTime}: ${p.value[0]}`);
128
+ });
129
+ lines.push('');
130
+ }
131
+
132
+ return lines.join('\n');
133
+ }
134
+
135
+ async function main() {
136
+ try {
137
+ const [relatedData, interestData] = await Promise.all([
138
+ fetchRelatedQueries(),
139
+ fetchInterestOverTime(),
140
+ ]);
141
+
142
+ let output;
143
+ switch (opts.output) {
144
+ case 'json':
145
+ output = formatJSON(relatedData, interestData);
146
+ break;
147
+ case 'markdown':
148
+ output = formatMarkdown(relatedData, interestData);
149
+ break;
150
+ default:
151
+ output = formatTable(relatedData, interestData);
152
+ }
153
+
154
+ console.log(output);
155
+
156
+ if (opts.file) {
157
+ const fs = await import('fs');
158
+ fs.writeFileSync(opts.file, output, 'utf-8');
159
+ console.log(`\n[Saved to ${opts.file}]`);
160
+ }
161
+
162
+ } catch (err) {
163
+ console.error('[Error]', err.message);
164
+ process.exit(1);
165
+ }
166
+ }
167
+
168
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "takomi",
3
- "version": "2.1.32",
3
+ "version": "2.1.34",
4
4
  "description": "🎯 Stop wrestling with AI. Start building with purpose. The artisan's toolkit for agent workflows, Codex skills, and original Takomi capabilities like 21st.dev integration.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -43,7 +43,7 @@ import {
43
43
  isStoreInitialized,
44
44
  } from './store.js';
45
45
  import { runDoctor } from './doctor.js';
46
- import { ensurePiInstalled, ensurePiSubagentsInstalled, launchTakomiHarness, printPiInstallResult, printPiSubagentsInstallResult, updatePiManagedPackages, printPiManagedPackageUpdateResult } from './pi-harness.js';
46
+ import { ensurePiInstalled, ensurePiSubagentsInstalled, launchTakomiHarness, printPiInstallResult, printPiSubagentsInstallResult, updatePiCliPackage, updatePiManagedPackages, printPiManagedPackageUpdateResult } from './pi-harness.js';
47
47
  import { installPiHarnessAssets, printPiInstallSummary, syncPiHarnessAssets, validatePiHarnessInstall } from './pi-installer.js';
48
48
  import { offerPiOptionalFeatures } from './pi-optional-features.js';
49
49
  import {
@@ -459,7 +459,7 @@ async function installPiTarget(options = {}) {
459
459
  console.log(pc.cyan('\n🧩 Optional Takomi Pi feature packs...\n'));
460
460
  await offerPiOptionalFeatures({ interactive: true });
461
461
  }
462
- console.log(pc.cyan('\n📦 Checking Pi-managed package updates...\n'));
462
+ console.log(pc.cyan('\n📦 Checking Pi-managed extension package updates...\n'));
463
463
  printPiManagedPackageUpdateResult(await updatePiManagedPackages());
464
464
  console.log(pc.dim('\nNext: cd <project> && takomi\n'));
465
465
  } catch (error) {
@@ -474,7 +474,7 @@ async function installPiOptionalFeaturesTarget() {
474
474
  printPiInstallResult(pi);
475
475
  if (!pi.ok) return;
476
476
  await offerPiOptionalFeatures({ interactive: true });
477
- console.log(pc.cyan('\n📦 Checking Pi-managed package updates...\n'));
477
+ console.log(pc.cyan('\n📦 Checking Pi-managed extension package updates...\n'));
478
478
  printPiManagedPackageUpdateResult(await updatePiManagedPackages());
479
479
  }
480
480
 
@@ -484,7 +484,7 @@ async function syncPiTarget() {
484
484
  const result = await syncPiHarnessAssets(program.version());
485
485
  const validation = await validatePiHarnessInstall();
486
486
  printPiInstallSummary(result, validation);
487
- console.log(pc.cyan('\n📦 Checking Pi-managed package updates...\n'));
487
+ console.log(pc.cyan('\n📦 Checking Pi-managed extension package updates...\n'));
488
488
  printPiManagedPackageUpdateResult(await updatePiManagedPackages());
489
489
  } catch (error) {
490
490
  console.log(pc.red('\nPi sync failed.'));
@@ -558,6 +558,8 @@ async function upgrade(target = 'all') {
558
558
  }
559
559
 
560
560
  if (normalizedTarget === 'pi') {
561
+ console.log(pc.cyan('\n📦 Updating Pi CLI...\n'));
562
+ printPiInstallResult(await updatePiCliPackage());
561
563
  await installPiTarget({ offerOptionalFeatures: false });
562
564
  return;
563
565
  }
@@ -567,6 +569,8 @@ async function upgrade(target = 'all') {
567
569
  return;
568
570
  }
569
571
 
572
+ console.log(pc.cyan('\n📦 Updating Pi CLI...\n'));
573
+ printPiInstallResult(await updatePiCliPackage());
570
574
  await installAllTargets({ offerOptionalFeatures: false });
571
575
  console.log(pc.magenta('\n✨ Fully upgraded. Next: run `takomi` from your project.\n'));
572
576
  }
@@ -1141,8 +1145,13 @@ program
1141
1145
  .command('stats [view]')
1142
1146
  .description('Show Takomi token, model, project, session, tool, and subagent usage stats')
1143
1147
  .option('--json', 'Print machine-readable JSON')
1148
+ .option('--full', 'Print the detailed debug-style stats view')
1144
1149
  .option('--home <path>', 'Override home directory for Pi history scanning')
1145
1150
  .option('--cwd <path>', 'Override project directory for project-local stats')
1151
+ .option('--sessions-root <paths>', 'Additional session JSONL root(s), separated by ; on Windows or : on POSIX')
1152
+ .option('--project-root <paths>', 'Discover project-local .pi/takomi and .pi/agent/sessions roots under these path(s)')
1153
+ .option('--run-history <path>', 'Additional subagent run-history JSONL file')
1154
+ .option('--stats-config <path>', 'Local stats config JSON file (defaults to ~/.takomi/stats.local.json, then .takomi-stats.local.json)')
1146
1155
  .option('--since <date|range>', 'Filter from YYYY-MM-DD or relative range like 7d, 4w, 3m')
1147
1156
  .option('--limit <n>', 'Rows per section', '8')
1148
1157
  .action((view, options) => printTakomiStats({ ...options, view, limit: Number(options.limit) || 8 }));