thoughtleaders-cli 0.7.0__py3-none-any.whl → 0.7.2__py3-none-any.whl
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.
- {thoughtleaders_cli-0.7.0.dist-info → thoughtleaders_cli-0.7.2.dist-info}/METADATA +3 -2
- {thoughtleaders_cli-0.7.0.dist-info → thoughtleaders_cli-0.7.2.dist-info}/RECORD +56 -53
- {thoughtleaders_cli-0.7.0.dist-info → thoughtleaders_cli-0.7.2.dist-info}/WHEEL +1 -1
- tl_cli/__init__.py +1 -1
- tl_cli/_plugin/.claude-plugin/plugin.json +1 -1
- tl_cli/_plugin/agents/youtube-comment-classifier.md +2 -2
- tl_cli/_plugin/skills/tl/SKILL.md +3 -0
- tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/SKILL.md +3 -2
- tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/_io_utf8.py +1 -1
- tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/analyze_channel.py +2 -2
- tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/report.py +1 -1
- tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/tl_cli.py +1 -1
- tl_cli/_plugin/skills/tl-import/SKILL.md +1 -0
- tl_cli/_plugin/skills/tl-keyword-research/SKILL.md +2 -0
- tl_cli/_plugin/skills/tl-report-builder/SKILL.md +1 -0
- tl_cli/_plugin/skills/tl-save-report/SKILL.md +3 -0
- tl_cli/_plugin/skills/tl-top-partnerships/SKILL.md +101 -0
- tl_cli/_plugin/skills/tl-top-partnerships/scripts/top_partnerships.py +335 -0
- tl_cli/_plugin/skills/tl-views-guarantee/SKILL.md +1 -0
- tl_cli/_typer_utils.py +23 -0
- tl_cli/auth/commands.py +2 -1
- tl_cli/commands/balance.py +2 -1
- tl_cli/commands/brands.py +2 -1
- tl_cli/commands/channels.py +2 -1
- tl_cli/commands/credits.py +2 -1
- tl_cli/commands/db.py +2 -1
- tl_cli/commands/deals.py +2 -1
- tl_cli/commands/describe.py +2 -1
- tl_cli/commands/doctor.py +3 -2
- tl_cli/commands/matches.py +2 -1
- tl_cli/commands/proposals.py +2 -1
- tl_cli/commands/recommender.py +2 -1
- tl_cli/commands/reports.py +2 -1
- tl_cli/commands/schema.py +2 -1
- tl_cli/commands/setup.py +41 -5
- tl_cli/commands/snapshots.py +2 -1
- tl_cli/commands/sponsorships.py +2 -1
- tl_cli/commands/uploads.py +2 -1
- tl_cli/commands/whoami.py +2 -1
- tl_cli/main.py +2 -0
- {thoughtleaders_cli-0.7.0.dist-info → thoughtleaders_cli-0.7.2.dist-info}/entry_points.txt +0 -0
- {thoughtleaders_cli-0.7.0.dist-info → thoughtleaders_cli-0.7.2.dist-info}/licenses/LICENSE +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/.gitignore +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/references/comment-patterns.md +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/references/peer-cohort.md +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/references/red-flags.md +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/references/scoring.md +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/anomaly_detector.py +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/comment_analyzer.py +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/comment_scraper.py +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/engagement_ratios.py +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/peer_cohort.py +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/resolve_channel.py +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/score.py +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/video_integrity.py +0 -0
- /tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/view_curves.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: thoughtleaders-cli
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Summary: ThoughtLeaders CLI — query sponsorship data, channels, brands, and intelligence
|
|
5
5
|
Project-URL: Homepage, https://thoughtleaders.io
|
|
6
6
|
Project-URL: Repository, https://github.com/ThoughtLeaders-io/thoughtleaders-cli
|
|
@@ -68,7 +68,7 @@ ThoughtLeaders CLI — query sponsorship data, channels, brands, and intelligenc
|
|
|
68
68
|
- [duckdb](https://duckdb.org/)
|
|
69
69
|
- [yt-dlp](https://github.com/yt-dlp/yt-dlp)
|
|
70
70
|
|
|
71
|
-
For automated installs on MacOS, prefer installing Homebrew and use the pipx package manager, but ask the user if they have the admin access (sudo) password first. If not, proceed by using `uv
|
|
71
|
+
For automated installs on MacOS, prefer installing Python and the requirements on Homebrew and use the pipx package manager, but ask the user if they have the admin access (sudo) password first. If not, proceed by using `uv`.
|
|
72
72
|
|
|
73
73
|
## Install
|
|
74
74
|
|
|
@@ -280,6 +280,7 @@ The plugin ships several focused skills (installed by all the `tl setup *` comma
|
|
|
280
280
|
- **`tl-report-builder`** — builds TL reports (channels / brands / sponsorships / videos) from natural-language requests. Produces an in-chat preview by default; saves a real campaign when the user is explicit ("save", "create the report").
|
|
281
281
|
- **`tl-import`** / **`bulk-import`** — superuser-only; bulk-add or exclude lists of channels, brands, videos, or sponsorships against a report.
|
|
282
282
|
- **`tl-views-guarantee`** — sizes a multi-video sponsorship buy for a channel, returning the video bundle size, views guarantee, and likelihood to hit.
|
|
283
|
+
- **`tl-top-partnerships`** — brand-user performance report. Ranks a brand's sold sponsorships by live eCPM vs the sold-date projection, aggregates per channel, and delivers a two-tab Google Sheet ("By Deal" / "By Channel") via `gws`. Uses only public CLI commands (`tl whoami`, `tl sponsorships list`).
|
|
283
284
|
|
|
284
285
|
## Output Formats
|
|
285
286
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
tl_cli/__init__.py,sha256=
|
|
1
|
+
tl_cli/__init__.py,sha256=w380YYlqGtwTYG78LJyZu5ljV8MmIBzKLk-R9Kq8Apw,112
|
|
2
2
|
tl_cli/_completions.py,sha256=kOyEUqC26vbYvyXWi513WX8fF73qQLR5WWuRSe_wqyk,164
|
|
3
|
+
tl_cli/_typer_utils.py,sha256=ZiZsCVmEznPvBw-dYbr3tu3zWZ0iN6kjoQmK3gMqD28,860
|
|
3
4
|
tl_cli/config.py,sha256=UV_OYTXuQnAIqbi_oVCXx0hhIdZWR678RRapVv51UwQ,1859
|
|
4
5
|
tl_cli/filters.py,sha256=jymgt21vl2d67yTXD_ceRIxTn6H6OYI5-QvQyE4Y4z0,2937
|
|
5
6
|
tl_cli/hints.py,sha256=cT8kuDtkAZqwXkc2RV0Yg_abofK-g9UiXwTTBunX78U,1557
|
|
6
|
-
tl_cli/main.py,sha256=
|
|
7
|
+
tl_cli/main.py,sha256=A_8b2SQjBKATxrjO7AGC5Ab1QWlP35gGo4TWzYZtlOM,5806
|
|
7
8
|
tl_cli/self_update.py,sha256=akXOWYgBX2otyaVlx9CDl04gG2s_hYigE2Vkpubt0SA,18302
|
|
8
9
|
tl_cli/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
tl_cli/auth/commands.py,sha256=
|
|
10
|
+
tl_cli/auth/commands.py,sha256=NtM5WGnReXrpZ3bysNudUYT_TcRRPE0Ho1EwbRgM_Ws,6285
|
|
10
11
|
tl_cli/auth/finalize.py,sha256=74x8U39dK4nhEnIUMKhX5rNsn1Qjjm8or1n1nUH0SbQ,3346
|
|
11
12
|
tl_cli/auth/login.py,sha256=6Jhfw7_eXGxZvUfNP33AZPRmnqmu_scvgt4AcOydsrE,10665
|
|
12
13
|
tl_cli/auth/pkce.py,sha256=4Q6Ip-TeZFNG9c3swXNi4gH7mdMkltKa62gZZNybt8U,658
|
|
@@ -16,64 +17,64 @@ tl_cli/client/errors.py,sha256=KcTIieHtiEeBBDXTtEBSWsMcx2qaQskMyc_2_0l9WM4,2597
|
|
|
16
17
|
tl_cli/client/http.py,sha256=pUJYYuT0q92_SwqCuMj3ozBthvchKuKL9v9U_eCQv20,4164
|
|
17
18
|
tl_cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
19
|
tl_cli/commands/_comments_common.py,sha256=x91WPSpDdV8AwE8Mwx4VtZQKWXBufsnBnC1lFD0Tzys,4522
|
|
19
|
-
tl_cli/commands/balance.py,sha256=
|
|
20
|
-
tl_cli/commands/brands.py,sha256=
|
|
20
|
+
tl_cli/commands/balance.py,sha256=JHSmKdAUNtd-9zlKZhit9_BmhHXrEk0kQ-oSlQ0Eo6Y,2732
|
|
21
|
+
tl_cli/commands/brands.py,sha256=rvYRrhkDhHDlvFpWrf8TtGbBt8KyNxHcVodjjFNpmHY,12443
|
|
21
22
|
tl_cli/commands/bulk_import.py,sha256=d4y1k_lD52LPJcCqXxEmyHIqcIwomZgbjqs1_QxPjeQ,4536
|
|
22
23
|
tl_cli/commands/changelog.py,sha256=D1PtDdHpawTlWqUHjKzVmv9yXLSU915UVmI3dZzEwyA,4241
|
|
23
|
-
tl_cli/commands/channels.py,sha256=
|
|
24
|
-
tl_cli/commands/credits.py,sha256=
|
|
25
|
-
tl_cli/commands/db.py,sha256=
|
|
26
|
-
tl_cli/commands/deals.py,sha256=
|
|
27
|
-
tl_cli/commands/describe.py,sha256=
|
|
28
|
-
tl_cli/commands/doctor.py,sha256=
|
|
29
|
-
tl_cli/commands/matches.py,sha256=
|
|
30
|
-
tl_cli/commands/proposals.py,sha256=
|
|
31
|
-
tl_cli/commands/recommender.py,sha256=
|
|
32
|
-
tl_cli/commands/reports.py,sha256=
|
|
33
|
-
tl_cli/commands/schema.py,sha256=
|
|
34
|
-
tl_cli/commands/setup.py,sha256=
|
|
35
|
-
tl_cli/commands/snapshots.py,sha256=
|
|
36
|
-
tl_cli/commands/sponsorships.py,sha256=
|
|
37
|
-
tl_cli/commands/uploads.py,sha256=
|
|
38
|
-
tl_cli/commands/whoami.py,sha256=
|
|
24
|
+
tl_cli/commands/channels.py,sha256=EgwTzweKsQEerBTwiWGCP1myCTW3KQFu4Om2j4Htfzk,17217
|
|
25
|
+
tl_cli/commands/credits.py,sha256=2xCht2e420LmaFBKNdKoMz8GlTh31qSWSlJAnVzoZic,7308
|
|
26
|
+
tl_cli/commands/db.py,sha256=rdIQrxT7sdrPEnBbByNHvPr2X6iIg-wb19X9bWYwDRc,5053
|
|
27
|
+
tl_cli/commands/deals.py,sha256=ZK9yneInsC6DXoCPS65oyLoVR0eRW1xdRlEN7oRp1pc,2174
|
|
28
|
+
tl_cli/commands/describe.py,sha256=Ox2B1hoVuJ6pJc_x5BJjAhEJhlae-el9zwoJKutw3X8,12232
|
|
29
|
+
tl_cli/commands/doctor.py,sha256=KUKglwhMc7B26XXy_3M0LkHu7wqfFO5T0YPHO1SH1VY,9024
|
|
30
|
+
tl_cli/commands/matches.py,sha256=K5o6B8FLECp7825dU4W3X8n-wuXvGJz57xpQPXeXQ-0,2886
|
|
31
|
+
tl_cli/commands/proposals.py,sha256=khsjorluIfgrJ22DiwzIAFcYD4JbirjkOBz1KuQ0Sdk,2918
|
|
32
|
+
tl_cli/commands/recommender.py,sha256=DIRvnSbV2TwvVUgA5luGJ7uQUOjHx2CULFsZVaqUYw4,18922
|
|
33
|
+
tl_cli/commands/reports.py,sha256=1QDJN6FrUmWCuvaMxN884_bVdy-l7anBuS2jkCZF1VQ,22543
|
|
34
|
+
tl_cli/commands/schema.py,sha256=GCBEE4fDatQhVasLKKr7bkGhELRZ0scYm_hUCbDYmuA,5985
|
|
35
|
+
tl_cli/commands/setup.py,sha256=QST6DCSxJHLFNX1UUJHwZ3hTDTnySATaV2Tc2JsdYYY,21920
|
|
36
|
+
tl_cli/commands/snapshots.py,sha256=mWxnZI_UBzbZZHsA3uP0Q7Gt2XsLLoRD5dRNGt-mGUE,3428
|
|
37
|
+
tl_cli/commands/sponsorships.py,sha256=MWjyaReMMhmVKAbrCBCVw_J6dzkML_TIo_2kyPOYQOM,10400
|
|
38
|
+
tl_cli/commands/uploads.py,sha256=Tf9tqAEm9FGe3A7sr_EDX9OzdNInCmrWNr10wWGuMUo,1526
|
|
39
|
+
tl_cli/commands/whoami.py,sha256=aUXwBRwh1vAGrvz8CKGfHYtEOKJCIDfwrGesKAwYZMk,7866
|
|
39
40
|
tl_cli/output/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
40
41
|
tl_cli/output/formatter.py,sha256=pqlKmb2nZ1Z2e1A9m8l5mgVemJinVAP4in1tUzFWHno,22522
|
|
41
42
|
tl_cli/_plugin/.claude-plugin/marketplace.json,sha256=l56PMmyjfGXNGlV30wRyOAe74B6gJNCVNCxgsBbSNxc,446
|
|
42
|
-
tl_cli/_plugin/.claude-plugin/plugin.json,sha256=
|
|
43
|
+
tl_cli/_plugin/.claude-plugin/plugin.json,sha256=_Im3uBChUbEhtgMa7p_Efg10yDoSSS0GtrAKAL_E6ME,466
|
|
43
44
|
tl_cli/_plugin/agents/tl-analyst.md,sha256=6J3X3NANkWg6OOUCvNirkN4ulIk80KSumPncDUBt75E,6761
|
|
44
|
-
tl_cli/_plugin/agents/youtube-comment-classifier.md,sha256=
|
|
45
|
+
tl_cli/_plugin/agents/youtube-comment-classifier.md,sha256=S5lr_htA98FIX0su8FJ2ntiHfbdK8OB2NQKC4lTnQcw,2178
|
|
45
46
|
tl_cli/_plugin/hooks/hooks.json,sha256=FSWibw1xAjA-suFV3fR8btIb2kQ82LQ08otTr-NpmFw,835
|
|
46
47
|
tl_cli/_plugin/hooks/scripts/load-tl-skill.mjs,sha256=EBsyZ-caei-CBJsRtqzJXJs_20O3H22MuVmDpu96umo,805
|
|
47
48
|
tl_cli/_plugin/hooks/scripts/post-usage.sh,sha256=WVvZLkZik6lbeZ20Kh-wgm4JkRFHFN0Uwl4C8S3Y0sY,759
|
|
48
49
|
tl_cli/_plugin/hooks/scripts/pre-check.sh,sha256=E9KeuXy6yeHEBOnOFW4hDW-Et-Dbp1Oh--3WXKfOX78,898
|
|
49
|
-
tl_cli/_plugin/skills/
|
|
50
|
-
tl_cli/_plugin/skills/channel-authenticity/SKILL.md,sha256=m9_x3OqPhC3nv7T6Orxus9Mn0l3603hc0YPDRTZvt4k,6244
|
|
51
|
-
tl_cli/_plugin/skills/channel-authenticity/references/comment-patterns.md,sha256=ne-2mSDxJDKb8HswRltvEIEh7iDDWckDqnWmdFQBbrI,2035
|
|
52
|
-
tl_cli/_plugin/skills/channel-authenticity/references/peer-cohort.md,sha256=fYlr6nucxCMbs2wj371mbfFyMp5W4183xUlvqNx5nPI,2160
|
|
53
|
-
tl_cli/_plugin/skills/channel-authenticity/references/red-flags.md,sha256=Lb4MnAMPWAIhOU_p1aRgcLQXtpvKnVF62i4Frzg3hzY,6383
|
|
54
|
-
tl_cli/_plugin/skills/channel-authenticity/references/scoring.md,sha256=QVXR-icnt52-iHBj7luaEi9HHEBPOz9-muPP2waL1CI,3773
|
|
55
|
-
tl_cli/_plugin/skills/channel-authenticity/scripts/_io_utf8.py,sha256=qmygcS79XCr9_awhFbUFc3oQV7K2fMXYbQevJv5QX4E,1893
|
|
56
|
-
tl_cli/_plugin/skills/channel-authenticity/scripts/analyze_channel.py,sha256=6TfoJdmDdaoO1PfZC1SAW6Y2Tq6ucjPyLCIzSLQ7yHM,7046
|
|
57
|
-
tl_cli/_plugin/skills/channel-authenticity/scripts/anomaly_detector.py,sha256=juE3O2BRv-QAtrsN_a27g53h2msdeyvkLY5y3v818aY,7565
|
|
58
|
-
tl_cli/_plugin/skills/channel-authenticity/scripts/comment_analyzer.py,sha256=83jJKV4eZR6FKeGOrMCYjcReR3AKemteiPDN-RpClb0,16142
|
|
59
|
-
tl_cli/_plugin/skills/channel-authenticity/scripts/comment_scraper.py,sha256=BNqfdVCZEO-6ZygHpTDn0vR_MjjZq1j0EHrpWcPCqyY,3472
|
|
60
|
-
tl_cli/_plugin/skills/channel-authenticity/scripts/engagement_ratios.py,sha256=my3oEWuoTxaVG_TJgFIKPVoXx108GPy5cNmHDTQhfX0,5875
|
|
61
|
-
tl_cli/_plugin/skills/channel-authenticity/scripts/peer_cohort.py,sha256=Ja2846q69ff_GmIWmc1SZvDSTe0ac8yUNJTmMNl_ids,5861
|
|
62
|
-
tl_cli/_plugin/skills/channel-authenticity/scripts/report.py,sha256=kjtG680ZwE8w-cKKizLuSQttV1zfMGM0cLct1PIvb44,4897
|
|
63
|
-
tl_cli/_plugin/skills/channel-authenticity/scripts/resolve_channel.py,sha256=mY0veC_HrzGSilHPUIEvk2JYjbrxDMCIvq2FD0Jc9p8,4387
|
|
64
|
-
tl_cli/_plugin/skills/channel-authenticity/scripts/score.py,sha256=LwhTMf9eyOYDrVC9_7ncHE3K9U9ztz_rcUQKLqpMlz0,2757
|
|
65
|
-
tl_cli/_plugin/skills/channel-authenticity/scripts/tl_cli.py,sha256=u4enE51TWhZ2xRZKCt6AXi9Jr7S433ZUJrDxX4Oz_wo,9025
|
|
66
|
-
tl_cli/_plugin/skills/channel-authenticity/scripts/video_integrity.py,sha256=Pj9cZkFHX-fwfmkSjicy_B04fQ3TW3gLrGliHwCwX5g,11120
|
|
67
|
-
tl_cli/_plugin/skills/channel-authenticity/scripts/view_curves.py,sha256=wx4cgi_HSOBDEy9bI_8RGnAFpY8q8xHOlF7DYojmi0c,4447
|
|
68
|
-
tl_cli/_plugin/skills/tl/SKILL.md,sha256=4Cr9Epf9lFm7M0d7vI99SfA37d_MmWq7kYR1egO2kY0,58071
|
|
50
|
+
tl_cli/_plugin/skills/tl/SKILL.md,sha256=fKxHgoe0oX1vFwVFUTzF95h4fq5fAmFlodqZr7cdbeA,58174
|
|
69
51
|
tl_cli/_plugin/skills/tl/references/business-glossary.md,sha256=FCS-qBOGpdJCmHdglRGRjAuTQAtzpxJNpMkEWThuvlI,17779
|
|
70
52
|
tl_cli/_plugin/skills/tl/references/elasticsearch-schema.md,sha256=OpHvixZ8UcZYJd8GdwgumryFyKwPAxj3AvPkl1QreMY,9316
|
|
71
53
|
tl_cli/_plugin/skills/tl/references/firebolt-schema.md,sha256=KagpSWWEWIRfsAWz271PvAqVbSPvWLoogWhCA_XFSZw,10642
|
|
72
54
|
tl_cli/_plugin/skills/tl/references/postgres-schema.md,sha256=sOSrRKGpqCeHB8-aqQXXDvfQ6EbF9j7jRsC0MNvbnIA,21927
|
|
73
|
-
tl_cli/_plugin/skills/tl-
|
|
74
|
-
tl_cli/_plugin/skills/tl-
|
|
55
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/.gitignore,sha256=EMeiIlgw10A-WzjTnENZs8jXAH9n2wT0Bn3vQ7tOP-E,121
|
|
56
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/SKILL.md,sha256=4vVIJu7DXjyahvuCWSeYQL2_H2KILKh7s5RyX-fBjpY,6289
|
|
57
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/references/comment-patterns.md,sha256=ne-2mSDxJDKb8HswRltvEIEh7iDDWckDqnWmdFQBbrI,2035
|
|
58
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/references/peer-cohort.md,sha256=fYlr6nucxCMbs2wj371mbfFyMp5W4183xUlvqNx5nPI,2160
|
|
59
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/references/red-flags.md,sha256=Lb4MnAMPWAIhOU_p1aRgcLQXtpvKnVF62i4Frzg3hzY,6383
|
|
60
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/references/scoring.md,sha256=QVXR-icnt52-iHBj7luaEi9HHEBPOz9-muPP2waL1CI,3773
|
|
61
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/scripts/_io_utf8.py,sha256=gBdf4ZhHoNxEthRcOov67bHACXDM7l5GfgfLru1MHVk,1896
|
|
62
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/scripts/analyze_channel.py,sha256=H9S55vi_9YC-12IolikuapNqPB9eDUmkKWEoiVbX6Fo,7052
|
|
63
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/scripts/anomaly_detector.py,sha256=juE3O2BRv-QAtrsN_a27g53h2msdeyvkLY5y3v818aY,7565
|
|
64
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/scripts/comment_analyzer.py,sha256=83jJKV4eZR6FKeGOrMCYjcReR3AKemteiPDN-RpClb0,16142
|
|
65
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/scripts/comment_scraper.py,sha256=BNqfdVCZEO-6ZygHpTDn0vR_MjjZq1j0EHrpWcPCqyY,3472
|
|
66
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/scripts/engagement_ratios.py,sha256=my3oEWuoTxaVG_TJgFIKPVoXx108GPy5cNmHDTQhfX0,5875
|
|
67
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/scripts/peer_cohort.py,sha256=Ja2846q69ff_GmIWmc1SZvDSTe0ac8yUNJTmMNl_ids,5861
|
|
68
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/scripts/report.py,sha256=3-6RgtxPB1KpZHSwHryANKiXNECO9NWxxv3UZWt_icQ,4900
|
|
69
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/scripts/resolve_channel.py,sha256=mY0veC_HrzGSilHPUIEvk2JYjbrxDMCIvq2FD0Jc9p8,4387
|
|
70
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/scripts/score.py,sha256=LwhTMf9eyOYDrVC9_7ncHE3K9U9ztz_rcUQKLqpMlz0,2757
|
|
71
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/scripts/tl_cli.py,sha256=lzW3l9TBtl6Q2w60b1B3iiIexgeiShVEJ8cQJlvWxZs,9028
|
|
72
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/scripts/video_integrity.py,sha256=Pj9cZkFHX-fwfmkSjicy_B04fQ3TW3gLrGliHwCwX5g,11120
|
|
73
|
+
tl_cli/_plugin/skills/tl-channel-authenticity/scripts/view_curves.py,sha256=wx4cgi_HSOBDEy9bI_8RGnAFpY8q8xHOlF7DYojmi0c,4447
|
|
74
|
+
tl_cli/_plugin/skills/tl-import/SKILL.md,sha256=k0-2yCpQ75yXk_wGrgSkInQeUeUp6-lne3vRXGcef8A,20245
|
|
75
|
+
tl_cli/_plugin/skills/tl-keyword-research/SKILL.md,sha256=xV_efeBwKpjHX1VleHDyr5vqpOhsP-EXH8UqN_SIIrE,10484
|
|
75
76
|
tl_cli/_plugin/skills/tl-keyword-research/scripts/probe.py,sha256=bM6p-AyaSOp8EpV9oxBVtMwolWCXjU48MisaEROeGZs,4796
|
|
76
|
-
tl_cli/_plugin/skills/tl-report-builder/SKILL.md,sha256=
|
|
77
|
+
tl_cli/_plugin/skills/tl-report-builder/SKILL.md,sha256=wGm7V0C8vqJAqWBfJOtGAAp19EI4xIL2TdY-KPxgLdU,144690
|
|
77
78
|
tl_cli/_plugin/skills/tl-report-builder/examples/e2e_findings.md,sha256=9JD8BA8QrW6d7TlWX6_vGVSvpo_EGPl5gihmSK86tiI,17453
|
|
78
79
|
tl_cli/_plugin/skills/tl-report-builder/examples/golden_queries.md,sha256=alBnZbHrSMPUFxrnI7IpW8DqEsmjm84jFAWYQH5G7kc,10619
|
|
79
80
|
tl_cli/_plugin/skills/tl-report-builder/references/columns_brands.md,sha256=mfxmyR3V5jz84jq6vx4fmafGVtKhYUIoKwVaEMkzHTg,3501
|
|
@@ -94,7 +95,7 @@ tl_cli/_plugin/skills/tl-report-builder/tools/sample_judge.md,sha256=Gl-wBNhsjni
|
|
|
94
95
|
tl_cli/_plugin/skills/tl-report-builder/tools/similar_channels.md,sha256=ta1Q-GelJ_nFaYFWXDMhhgkTXRRYUSxhgjKdAeHtCrY,2071
|
|
95
96
|
tl_cli/_plugin/skills/tl-report-builder/tools/topic_matcher.md,sha256=KIuqCFm_zcgQcxDRoAisFnN64P9M-ueKfy8qmWIgYAg,13395
|
|
96
97
|
tl_cli/_plugin/skills/tl-report-builder/tools/widget_builder.md,sha256=da2dJN7M1j9QXtlEPs0CGUp5GHbO-tsgMuJRIxQAtAY,14392
|
|
97
|
-
tl_cli/_plugin/skills/tl-save-report/SKILL.md,sha256=
|
|
98
|
+
tl_cli/_plugin/skills/tl-save-report/SKILL.md,sha256=B3sv_G3pfIkqPLReez6RAwy5Dx6Nf4kz1C7UdaIAZLo,36976
|
|
98
99
|
tl_cli/_plugin/skills/tl-save-report/references/columns_brands.md,sha256=H5G308GOzMWvWw6smkPGdb2CBuuxkrojCpJgWS9X4sA,3559
|
|
99
100
|
tl_cli/_plugin/skills/tl-save-report/references/columns_channels.md,sha256=g57ET_VI611lB7fVrGwYFvTDqMkNB63OmmfrnbMZF1I,4684
|
|
100
101
|
tl_cli/_plugin/skills/tl-save-report/references/columns_content.md,sha256=Y9YL5sm7zK44vSHTXOV4NY7nSOcJ9i3D0HFCo1g63WU,3466
|
|
@@ -106,10 +107,12 @@ tl_cli/_plugin/skills/tl-save-report/references/sortable_columns.json,sha256=WxA
|
|
|
106
107
|
tl_cli/_plugin/skills/tl-save-report/references/sponsorship_filterset_schema.json,sha256=MlbxtBwCArdCmKynrZU6UL0Ve5Dp15tx6iIQJ5xhivY,10753
|
|
107
108
|
tl_cli/_plugin/skills/tl-save-report/references/sponsorship_widget_schema.json,sha256=bCCl1yF9PBdJndvlT6Ek5UbDYHMvufByKNDN1aunpHE,9530
|
|
108
109
|
tl_cli/_plugin/skills/tl-save-report/references/widgets.md,sha256=OFN6FOMjkBqiFN5EHP_pUqrp6Zqou5JuAXJ75cHWyyE,9798
|
|
109
|
-
tl_cli/_plugin/skills/tl-
|
|
110
|
+
tl_cli/_plugin/skills/tl-top-partnerships/SKILL.md,sha256=hvH05hIaGlc0RfTE0GLBtDiB6043TmdIYOOczfOEqLM,6517
|
|
111
|
+
tl_cli/_plugin/skills/tl-top-partnerships/scripts/top_partnerships.py,sha256=_13W6-HuD_jtl7AWQQcZQ0SQO9qODMymlcL-1s4-VwU,13248
|
|
112
|
+
tl_cli/_plugin/skills/tl-views-guarantee/SKILL.md,sha256=IH7q1WJDWri9TWJMiga1FMGJO_GKSbWwaDS6CVNZ9c0,9270
|
|
110
113
|
tl_cli/_plugin/skills/tl-views-guarantee/scripts/vg.py,sha256=Qp5poinHEqh9374anq0bLtlxj2YL6ipBicaT960-Cws,15825
|
|
111
|
-
thoughtleaders_cli-0.7.
|
|
112
|
-
thoughtleaders_cli-0.7.
|
|
113
|
-
thoughtleaders_cli-0.7.
|
|
114
|
-
thoughtleaders_cli-0.7.
|
|
115
|
-
thoughtleaders_cli-0.7.
|
|
114
|
+
thoughtleaders_cli-0.7.2.dist-info/METADATA,sha256=7BN2D4RB5Aq2zWM6krJwjpR6IAFOZczDvjnUeN67q0A,18452
|
|
115
|
+
thoughtleaders_cli-0.7.2.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
116
|
+
thoughtleaders_cli-0.7.2.dist-info/entry_points.txt,sha256=umZp-1BkGkHDG0bNZXpTXrjwW0HGf9IDFN40eAWuuvg,39
|
|
117
|
+
thoughtleaders_cli-0.7.2.dist-info/licenses/LICENSE,sha256=RUfdfLsn6jygiyrnnVUHt6r4IPwr2rbDm9Kixgtu8fo,1071
|
|
118
|
+
thoughtleaders_cli-0.7.2.dist-info/RECORD,,
|
tl_cli/__init__.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: youtube-comment-classifier
|
|
3
3
|
description: >
|
|
4
4
|
Classifies a batch of YouTube comments as organic vs bot/spam/template for
|
|
5
|
-
the channel-authenticity skill's fake-engagement detection. Use when you
|
|
5
|
+
the tl-channel-authenticity skill's fake-engagement detection. Use when you
|
|
6
6
|
have a JSON array of scraped comments and need a fast, cheap per-comment
|
|
7
7
|
authenticity judgment. Returns strict JSON only.
|
|
8
8
|
model: haiku
|
|
@@ -14,7 +14,7 @@ color: yellow
|
|
|
14
14
|
|
|
15
15
|
You judge whether YouTube comments come from a real, engaged human audience or
|
|
16
16
|
from engagement padding (bots, comment farms, generic filler). You are used by
|
|
17
|
-
the `channel-authenticity` skill to vet channels before ThoughtLeaders books a
|
|
17
|
+
the `tl-channel-authenticity` skill to vet channels before ThoughtLeaders books a
|
|
18
18
|
paid sponsorship, so false "organic" verdicts cost real money — be skeptical.
|
|
19
19
|
|
|
20
20
|
## Input
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tl
|
|
3
|
+
tl-blurb: data analyst (smart query router)
|
|
3
4
|
description: |
|
|
4
5
|
Query and analyze YouTube sponsorship data using the `tl` CLI. Use this skill for finding channels, brands and sponsorships, and for data exploration, including counts, metrics, trends, time-series, distributions, single-record drill-downs, revenue / pipeline-weighting math, view-curve analysis, cross-source business questions. Examples: "How many deals did we close last quarter?", "What's the weighted pipeline by sales owner?", "Show me the view curve for video X", "Find mentions of Surfshark in transcripts", "Investigate this video", "Find channels...", "Find brands...".
|
|
5
6
|
---
|
|
@@ -433,6 +434,8 @@ If unsure about what information to find where, read the [references/postgresql-
|
|
|
433
434
|
|
|
434
435
|
If a user asks for one of the **Unavailable** items, say so explicitly and propose the closest `tl`-based approximation rather than silently degrading.
|
|
435
436
|
|
|
437
|
+
If the user requests a chart, create it as a SVG graphic.
|
|
438
|
+
|
|
436
439
|
### Discovery & system
|
|
437
440
|
```bash
|
|
438
441
|
tl describe # List all resources with credit costs (free)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: channel-authenticity
|
|
2
|
+
name: tl-channel-authenticity
|
|
3
|
+
tl-blurb: vet a channel for fake views
|
|
3
4
|
description: >
|
|
4
5
|
Detect non-organic views / fake engagement / bot comments on a YouTube
|
|
5
6
|
channel before booking (or after delivering) a sponsorship. Use when asked
|
|
@@ -33,7 +34,7 @@ investigations.
|
|
|
33
34
|
## Setup check
|
|
34
35
|
|
|
35
36
|
```bash
|
|
36
|
-
cd .claude/skills/channel-authenticity/scripts
|
|
37
|
+
cd .claude/skills/tl-channel-authenticity/scripts
|
|
37
38
|
python3 tl_cli.py preflight # must print "OK"
|
|
38
39
|
```
|
|
39
40
|
If this errors with `cli_unavailable`, tell the user to run `tl auth login`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Shared UTF-8 I/O setup for the channel-authenticity scripts.
|
|
1
|
+
"""Shared UTF-8 I/O setup for the tl-channel-authenticity scripts.
|
|
2
2
|
|
|
3
3
|
YouTube data is full of non-ASCII: channel names, comment text, emoji.
|
|
4
4
|
On POSIX the default I/O encoding is already UTF-8, but on Windows the
|
tl_cli/_plugin/skills/{channel-authenticity → tl-channel-authenticity}/scripts/analyze_channel.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""channel-authenticity orchestrator — two-phase (subagent in the middle).
|
|
2
|
+
"""tl-channel-authenticity orchestrator — two-phase (subagent in the middle).
|
|
3
3
|
|
|
4
4
|
Phase 1 (collect):
|
|
5
5
|
analyze_channel.py "<ref>"
|
|
@@ -128,7 +128,7 @@ def finalize(state_path: str, llm_paths: list[str]) -> dict:
|
|
|
128
128
|
|
|
129
129
|
|
|
130
130
|
def main() -> None:
|
|
131
|
-
ap = argparse.ArgumentParser(description="channel-authenticity orchestrator")
|
|
131
|
+
ap = argparse.ArgumentParser(description="tl-channel-authenticity orchestrator")
|
|
132
132
|
ap.add_argument("ref", nargs="?", help="channel handle/url/id or adlink:<id>")
|
|
133
133
|
ap.add_argument(
|
|
134
134
|
"--finalize",
|
|
@@ -120,7 +120,7 @@ def render(state: dict) -> str:
|
|
|
120
120
|
L.append("")
|
|
121
121
|
L.append("---")
|
|
122
122
|
L.append(
|
|
123
|
-
"_Generated by the `channel-authenticity` skill. Data via the "
|
|
123
|
+
"_Generated by the `tl-channel-authenticity` skill. Data via the "
|
|
124
124
|
"ThoughtLeaders CLI; comments scraped fresh from YouTube._"
|
|
125
125
|
)
|
|
126
126
|
return "\n".join(L)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""Single data-access seam for the channel-authenticity skill.
|
|
2
|
+
"""Single data-access seam for the tl-channel-authenticity skill.
|
|
3
3
|
|
|
4
4
|
Every TL data getter shells out to the ``tl`` CLI (``tl db pg/fb/es``,
|
|
5
5
|
``tl channels similar``), so the skill works for anyone with a ThoughtLeaders
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tl-import
|
|
3
|
+
tl-blurb: bulk-import lists into a report
|
|
3
4
|
description: Import a list of channels, brands, uploads (videos), or sponsorships into a ThoughtLeaders report — either an existing report (caller supplies `campaign_id` or a TL report URL) or a fresh new one (skill creates a minimal container, then populates). Superuser-only. **Trigger on explicit intent to import the listed entities into a report**, NOT on the mere presence of a list (a user can paste a list and want analysis, comparison, or similar-channel discovery — those go to `tl-cli:tl`). The deciding question is: *would the user be satisfied if those exact entities ended up as the report's contents, no transformation?* If yes, this is the skill. Phrasings: "import these channels into report 1234", "add brands to campaign 5678", "exclude these channels from report Z", "bulk-add these videos to report X", "create a new report with these channels: <list>", "make a campaign containing these brands: <list>".
|
|
4
5
|
---
|
|
5
6
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tl-keyword-research
|
|
3
|
+
tl-blurb: rank content-search keywords
|
|
3
4
|
description: |
|
|
4
5
|
Broaden and rank a set of content-search keywords. Invoke when the user wants to find videos or channels by content keywords (topics, concepts, niches) — not by ID or exact name. Takes one or more seed keywords (or an NL phrase), proposes related candidates, probes Elasticsearch for each one against the `title` / `summary` / `transcript` fields, and returns a strict JSON object `{"keywords":[{"keyword","count"},...]}` sorted descending by document count. The output is meant to feed the next step (typically a `tl db es` content search with the surviving high-count keywords).
|
|
5
6
|
---
|
|
@@ -163,3 +164,4 @@ Each probe is `size:0` + `track_total_hits:true` with no aggregations — no row
|
|
|
163
164
|
5. `keywords` array is sorted descending by `count`.
|
|
164
165
|
6. Each entry has exactly `keyword` (string) and `count` (integer).
|
|
165
166
|
7. The seed keyword(s) appear in the output.
|
|
167
|
+
8. If the user requests a chart, create it as a SVG graphic
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tl-report-builder
|
|
3
|
+
tl-blurb: build a TL report from scratch
|
|
3
4
|
description: |
|
|
4
5
|
**MANUAL-INVOCATION-ONLY skill — do NOT auto-trigger on natural-language report requests.** This skill is invoked explicitly by the user (via the `/tl-report-builder` slash command, by naming the skill directly, or via some other unambiguous indication). Phrases like "build me a report", "make a campaign", "find me channels with filters Y", or "save this as a report" do NOT route here automatically. Those phrases go to other skills: the `tl` skill (for analysis / exploration of channels / brands / videos / sponsorships), `tl-save-report` (for persisting an in-chat session's result set as a saved report — filter-style or list-style), or `tl-import` (for adding identifiers to an existing report). This skill itself builds a brand-new TL report config from scratch through a heavy four-phase orchestration (routing → schema + validation → columns → widgets), covering the four report types: content/videos (1), brands (2), channels (3), sponsorships/deals (8). Only fire it when the user has explicitly chosen this path — there's almost always a lighter skill that's the right answer.
|
|
5
6
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tl-save-report
|
|
3
|
+
tl-blurb: save a session as a report
|
|
3
4
|
description: |
|
|
4
5
|
Save the results of an in-chat data-exploration session as a TL report. Triggers when the user wants to persist a channels / brands / videos (uploads) / sponsorships list or filtered set they've been working with — phrases like "save this as a report", "save the list", "turn this into a campaign", "persist this", "make a report from what you found", "save the result", "I want to come back to this".
|
|
5
6
|
---
|
|
@@ -502,6 +503,8 @@ Echo the saved URL + ID, plus a follow-up offer for refinement:
|
|
|
502
503
|
|
|
503
504
|
The follow-up offer matters because **FilterSet changes (keywords, demographics, M2M lists) can't be patched in place** via `tl reports update` — they require saving a new variant. Surface that limitation only if the user actually asks to change FilterSet fields.
|
|
504
505
|
|
|
506
|
+
If the user requests a chart, create it as a SVG graphic.
|
|
507
|
+
|
|
505
508
|
### On failure
|
|
506
509
|
|
|
507
510
|
If the command exits non-zero, the CLI prints the error on stderr (shape: `Error (NNN): <detail>` for most codes; specific lines for 401/402/403). **Surface the error verbatim** — do NOT silently report success.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tl-top-partnerships
|
|
3
|
+
description: External brand-user performance report. Ranks a brand's sponsorships by effective CPM once the sponsored videos went live, and compares live eCPM against the sold-date projection. Use whenever a brand user asks "which of my sponsorships performed best", "top partnerships this year", "best ROI deals", "effective CPM on my deals", "which sponsorships overperformed", "/top-partnerships", or any variation of "show me my best-performing sponsorships". This is the brand-side equivalent of internal performance reporting — fire it eagerly any time a brand wants to look back at their booked deals through a performance lens, even if they don't say the words "CPM" or "eCPM".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Top Partnerships (Brand-side)
|
|
7
|
+
|
|
8
|
+
Helps a brand look back at their sold sponsorships and see which ones delivered the lowest effective CPM (eCPM) once the videos went live, vs the projection at sale.
|
|
9
|
+
|
|
10
|
+
## Triggers
|
|
11
|
+
|
|
12
|
+
- `/top-partnerships` — defaults to calendar YTD
|
|
13
|
+
- `/top-partnerships <range>` — e.g. `/top-partnerships 2025`, `/top-partnerships "last 12 months"`, `/top-partnerships "Q1 2026"`
|
|
14
|
+
- Natural language: "top partnerships this year", "best sponsorships", "which deals performed best", "effective CPM on my deals", "show me my best ROI sponsorships"
|
|
15
|
+
|
|
16
|
+
## What this skill computes
|
|
17
|
+
|
|
18
|
+
For every sold sponsorship the brand has where the video has actually gone live (has a `publish_date` and a non-null live `views` count):
|
|
19
|
+
|
|
20
|
+
- **Sold-date eCPM** = `price / projected_views_at_purchase_date * 1000`
|
|
21
|
+
- The projection captured on the adlink at the moment the deal was sold. This is the eCPM the brand "agreed to."
|
|
22
|
+
- **Live eCPM** = `price / views * 1000`
|
|
23
|
+
- The actual eCPM now that the video has accumulated views.
|
|
24
|
+
- **View ratio** = `views / projected_views_at_purchase_date`
|
|
25
|
+
- >1 means the video out-delivered its projection.
|
|
26
|
+
- **Delta** = `live_eCPM - sold_date_eCPM`
|
|
27
|
+
- Negative delta = the deal got *cheaper* per view than promised (good for the brand). Positive delta = the deal underdelivered.
|
|
28
|
+
|
|
29
|
+
It also pulls **future bookings** — any sponsorship with status sold / proposal_approved / pending and a send date strictly after today — and tags each deal and each channel with the earliest future send date, or "Re-book - no future spot" if none exists. This turns the report into an actionable list, not just a backward look.
|
|
30
|
+
|
|
31
|
+
## Output
|
|
32
|
+
|
|
33
|
+
A Google Sheet with two tabs, owned by the caller's Google account:
|
|
34
|
+
|
|
35
|
+
- **By Deal** — one row per sponsorship, ranked by live eCPM (best first). Columns: rank, channel, title, video_url, send_date, publish_date, price, promised_views, live_views, view_ratio, sold_date_ecpm, live_ecpm, delta_ecpm, measurable, next_booking.
|
|
36
|
+
- **By Channel** — one row per channel, aggregated across all that channel's deals in range. Combined live eCPM is `sum(price) / sum(live_views) * 1000` (volume-weighted, not an average of CPMs). Sorted by combined live eCPM. Columns: channel, deals, measurable_deals, total_price_usd, total_promised_views, total_live_views, view_ratio, sold_date_ecpm, live_ecpm, delta_ecpm, next_booking.
|
|
37
|
+
|
|
38
|
+
In chat: a short summary + top-10 channels table + the sheet URL.
|
|
39
|
+
|
|
40
|
+
## Workflow
|
|
41
|
+
|
|
42
|
+
### Step 1 — Resolve the brand
|
|
43
|
+
|
|
44
|
+
Run `tl whoami --json` and read the `brands` array.
|
|
45
|
+
|
|
46
|
+
- One brand → use it silently.
|
|
47
|
+
- Zero brands → tell the user this skill is for brand-user profiles and stop.
|
|
48
|
+
- Multiple brands → ask which one. Don't guess.
|
|
49
|
+
|
|
50
|
+
### Step 2 — Resolve the time range
|
|
51
|
+
|
|
52
|
+
Default = calendar YTD (Jan 1 of the current year through today).
|
|
53
|
+
|
|
54
|
+
Accept these forms in the user's input:
|
|
55
|
+
|
|
56
|
+
- `2025` or `"2024"` → that full calendar year
|
|
57
|
+
- `"last 12 months"` → trailing 12 months ending today
|
|
58
|
+
- `"Q1 2026"`, `"Q4 2025"` → that quarter
|
|
59
|
+
- `"YTD"` → explicit current YTD
|
|
60
|
+
- Anything else → ask the user to clarify, don't silently pick
|
|
61
|
+
|
|
62
|
+
Convert to a `send-date-start` / `send-date-end` pair (YYYY-MM-DD strings). Use `send_date` as the time anchor because that is when the sponsorship actually ran for the brand — purchase_date can be months earlier.
|
|
63
|
+
|
|
64
|
+
### Step 3 — Run the script
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
python3 <SKILL_DIR>/scripts/top_partnerships.py \
|
|
68
|
+
--brand "<BRAND_NAME>" \
|
|
69
|
+
--send-date-start <YYYY-MM-DD> \
|
|
70
|
+
--send-date-end <YYYY-MM-DD>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`<SKILL_DIR>` resolves to this skill's directory at invocation time (same convention as `tl-views-guarantee`, `tl-keyword-research`).
|
|
74
|
+
|
|
75
|
+
The script does everything: pulls sold deals in range (paginated), pulls all future bookings, computes per-deal and per-channel metrics, creates a Google Sheet with two tabs, shares it back to the caller, and prints a markdown summary plus the sheet URL.
|
|
76
|
+
|
|
77
|
+
It uses `tl` for data and `gws` for sheet creation. Both must be on PATH and authed.
|
|
78
|
+
|
|
79
|
+
### Step 4 — Present the result
|
|
80
|
+
|
|
81
|
+
Take the script's stdout as-is. It already contains:
|
|
82
|
+
|
|
83
|
+
1. **Summary line** — total sold deals, measurable count, median live eCPM, count overperforming.
|
|
84
|
+
2. **Top 10 channels by combined live eCPM** — markdown table with the Next booking column bolded when it says "Re-book."
|
|
85
|
+
3. **Sheet URL** — point the user at the two tabs.
|
|
86
|
+
|
|
87
|
+
If more than half the top-10 channels show "Re-book", call that out in one sentence as the headline action item. If most of the top channels already have follow-ups booked, congratulate briefly and stop.
|
|
88
|
+
|
|
89
|
+
Keep the writeup tight. No em dashes, no "just wanted to", no hedging. The data does the talking.
|
|
90
|
+
|
|
91
|
+
## Brand-user mode notes
|
|
92
|
+
|
|
93
|
+
- This skill assumes a brand-user `tl` auth. It uses only public CLI commands (`tl whoami`, `tl sponsorships list`) — no `tl db pg` and no Elasticsearch.
|
|
94
|
+
- The `tl sponsorships list` endpoint already filters to deals the calling profile is allowed to see, so passing `brand:"<name>"` is a belt-and-braces filter rather than a privacy boundary.
|
|
95
|
+
- View counts come from TL's own tracking on the `views` field returned by the CLI. They're the same numbers the brand sees in the TL dashboard, so the eCPMs are reconcilable with what they see in-app.
|
|
96
|
+
- Don't include creators' contact emails, internal notes, or owner_* fields in the brand-facing output. The script already drops them from the CSV.
|
|
97
|
+
|
|
98
|
+
## Edge cases worth mentioning to the user (only if they apply)
|
|
99
|
+
|
|
100
|
+
- A deal that ran very recently (last 14-28 days) may show a misleadingly high Live eCPM because views are still accumulating. Mention this only if more than half the top-10 deals have a send date inside the last 28 days.
|
|
101
|
+
- If the brand has zero measurable deals in the range, say so plainly and suggest broadening the range (e.g., last 12 months).
|