thoughtleaders-cli 0.6.39__tar.gz → 0.6.41__tar.gz
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.6.39 → thoughtleaders_cli-0.6.41}/.claude-plugin/plugin.json +1 -1
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/PKG-INFO +1 -1
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/pyproject.toml +1 -1
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/__init__.py +1 -1
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/auth/commands.py +65 -1
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/doctor.py +6 -2
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/setup.py +161 -37
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/self_update.py +6 -1
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/.claude-plugin/marketplace.json +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/.github/workflows/python-publish.yml +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/.gitignore +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/AGENTS.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/CLAUDE.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/LICENSE +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/README.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/agents/tl-analyst.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/docs/architecture.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/hooks/hooks.json +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/hooks/scripts/load-tl-skill.mjs +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/hooks/scripts/post-usage.sh +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/hooks/scripts/pre-check.sh +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl/SKILL.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl/references/business-glossary.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl/references/elasticsearch-schema.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl/references/firebolt-schema.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl/references/postgres-schema.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-import/SKILL.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/SKILL.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/examples/e2e_findings.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/examples/golden_queries.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/references/columns_brands.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/references/columns_channels.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/references/columns_content.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/references/columns_sponsorships.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/references/intelligence_filterset_schema.json +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/references/intelligence_widget_schema.json +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/references/report_glossary.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/references/sortable_columns.json +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/references/sponsorship_filterset_schema.json +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/references/sponsorship_widget_schema.json +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/references/widgets.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/tools/column_builder.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/tools/database_query.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/tools/keyword_research.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/tools/name_resolver.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/tools/sample_judge.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/tools/similar_channels.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/tools/topic_matcher.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl-report-builder/tools/widget_builder.md +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/_completions.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/auth/__init__.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/auth/finalize.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/auth/login.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/auth/pkce.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/auth/token_store.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/client/__init__.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/client/errors.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/client/http.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/__init__.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/_comments_common.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/ask.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/balance.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/brands.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/bulk_import.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/changelog.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/channels.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/credits.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/db.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/deals.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/describe.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/matches.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/proposals.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/recommender.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/reports.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/schema.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/snapshots.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/sponsorships.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/uploads.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/whoami.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/config.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/filters.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/hints.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/main.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/output/__init__.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/output/formatter.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/tests/__init__.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/tests/test_auth.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/tests/test_filters.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/tests/test_http_auth.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/tests/test_output.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/tests/test_reports.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/tests/test_sponsorships.py +0 -0
- {thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: thoughtleaders-cli
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.41
|
|
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
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Auth CLI commands: tl auth login/logout/status."""
|
|
2
2
|
|
|
3
|
+
import sys
|
|
3
4
|
import time
|
|
4
5
|
|
|
5
6
|
import typer
|
|
@@ -14,6 +15,69 @@ app = typer.Typer(help="Authentication commands")
|
|
|
14
15
|
console = Console(stderr=True)
|
|
15
16
|
|
|
16
17
|
|
|
18
|
+
def _read_masked(prompt: str) -> str:
|
|
19
|
+
"""Read a line of input echoing `*` for each character.
|
|
20
|
+
|
|
21
|
+
Falls back to plain `input()` when stdin is not a TTY (piped input,
|
|
22
|
+
test harness). Uses stdlib `termios` on Unix and `msvcrt` on Windows
|
|
23
|
+
so no extra dependency is needed.
|
|
24
|
+
"""
|
|
25
|
+
if not sys.stdin.isatty():
|
|
26
|
+
return input(prompt)
|
|
27
|
+
|
|
28
|
+
sys.stdout.write(prompt)
|
|
29
|
+
sys.stdout.flush()
|
|
30
|
+
|
|
31
|
+
buf: list[str] = []
|
|
32
|
+
if sys.platform == 'win32':
|
|
33
|
+
import msvcrt
|
|
34
|
+
while True:
|
|
35
|
+
ch = msvcrt.getwch()
|
|
36
|
+
if ch in ('\r', '\n'):
|
|
37
|
+
sys.stdout.write('\n')
|
|
38
|
+
sys.stdout.flush()
|
|
39
|
+
break
|
|
40
|
+
if ch == '\x03': # Ctrl-C
|
|
41
|
+
raise KeyboardInterrupt
|
|
42
|
+
if ch in ('\b', '\x7f'):
|
|
43
|
+
if buf:
|
|
44
|
+
buf.pop()
|
|
45
|
+
sys.stdout.write('\b \b')
|
|
46
|
+
sys.stdout.flush()
|
|
47
|
+
continue
|
|
48
|
+
buf.append(ch)
|
|
49
|
+
sys.stdout.write('*')
|
|
50
|
+
sys.stdout.flush()
|
|
51
|
+
else:
|
|
52
|
+
import termios
|
|
53
|
+
import tty
|
|
54
|
+
fd = sys.stdin.fileno()
|
|
55
|
+
old = termios.tcgetattr(fd)
|
|
56
|
+
try:
|
|
57
|
+
tty.setcbreak(fd)
|
|
58
|
+
while True:
|
|
59
|
+
ch = sys.stdin.read(1)
|
|
60
|
+
if ch in ('\r', '\n'):
|
|
61
|
+
sys.stdout.write('\n')
|
|
62
|
+
sys.stdout.flush()
|
|
63
|
+
break
|
|
64
|
+
if ch == '\x03':
|
|
65
|
+
raise KeyboardInterrupt
|
|
66
|
+
if ch in ('\b', '\x7f'):
|
|
67
|
+
if buf:
|
|
68
|
+
buf.pop()
|
|
69
|
+
sys.stdout.write('\b \b')
|
|
70
|
+
sys.stdout.flush()
|
|
71
|
+
continue
|
|
72
|
+
buf.append(ch)
|
|
73
|
+
sys.stdout.write('*')
|
|
74
|
+
sys.stdout.flush()
|
|
75
|
+
finally:
|
|
76
|
+
termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
|
77
|
+
|
|
78
|
+
return ''.join(buf)
|
|
79
|
+
|
|
80
|
+
|
|
17
81
|
@app.command("login", help="Log in to ThoughtLeaders.")
|
|
18
82
|
def login_cmd() -> None:
|
|
19
83
|
"""Log in to ThoughtLeaders.
|
|
@@ -58,7 +122,7 @@ def _login_api_key() -> None:
|
|
|
58
122
|
from tl_cli.client.errors import ApiError
|
|
59
123
|
from tl_cli.client.http import get_client
|
|
60
124
|
|
|
61
|
-
key =
|
|
125
|
+
key = _read_masked("Paste your API key: ").strip()
|
|
62
126
|
if not key:
|
|
63
127
|
console.print("[red]No key provided.[/red]")
|
|
64
128
|
raise typer.Exit(1)
|
|
@@ -148,10 +148,14 @@ def doctor(ctx: typer.Context) -> None:
|
|
|
148
148
|
console.print(" Auth: [red]not logged in[/red]")
|
|
149
149
|
all_ok = False
|
|
150
150
|
elif tokens.is_expired:
|
|
151
|
-
console.print(
|
|
151
|
+
console.print(
|
|
152
|
+
f" Auth: [yellow]token expired[/yellow] (OAuth2, {tokens.email})"
|
|
153
|
+
)
|
|
152
154
|
all_ok = False
|
|
153
155
|
else:
|
|
154
|
-
|
|
156
|
+
method = "API key" if tokens.is_api_key else "OAuth2"
|
|
157
|
+
identity = tokens.email or ("via API key" if tokens.is_api_key else "unknown")
|
|
158
|
+
console.print(f" Auth: [green]ok[/green] ({method}, {identity})")
|
|
155
159
|
|
|
156
160
|
# Connectivity + balance + latency timing. The first /balance call
|
|
157
161
|
# doubles as the connectivity probe; subsequent calls feed the
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
"""tl setup — Install Claude Code plugin and other integrations.
|
|
1
|
+
"""tl setup — Install Claude Code plugin and other integrations.
|
|
2
|
+
|
|
3
|
+
Agents-style installs (Gemini / Codex): both CLIs read skills from
|
|
4
|
+
`~/.agents/skills/`, so they share a single install target. Any `tl
|
|
5
|
+
setup …` command that installs skill files also mirrors them there
|
|
6
|
+
whenever either `gemini` or `codex` is on PATH. Behaviour follows the
|
|
7
|
+
OpenCode pattern (full per-skill tree copy, .tl-version stamp).
|
|
8
|
+
"""
|
|
2
9
|
|
|
3
10
|
import json
|
|
4
11
|
import shutil
|
|
@@ -10,7 +17,7 @@ from rich.console import Console
|
|
|
10
17
|
|
|
11
18
|
from tl_cli import __version__
|
|
12
19
|
|
|
13
|
-
app = typer.Typer(help="Set up integrations (Claude Code, OpenCode)")
|
|
20
|
+
app = typer.Typer(help="Set up integrations (Claude Code, OpenCode, Gemini, Codex)")
|
|
14
21
|
console = Console(stderr=True)
|
|
15
22
|
|
|
16
23
|
MARKETPLACE_SOURCE = "ThoughtLeaders-io/thoughtleaders-cli"
|
|
@@ -25,6 +32,13 @@ CLAUDE_COMMANDS_DIR = CLAUDE_HOME / "commands"
|
|
|
25
32
|
|
|
26
33
|
OPENCODE_SKILLS_DIR = Path.home() / ".config" / "opencode" / "skills"
|
|
27
34
|
|
|
35
|
+
# Shared install target for the "agents-style" CLIs that read skills from
|
|
36
|
+
# `~/.agents/skills/`. Whenever any of these binaries is on PATH we mirror
|
|
37
|
+
# the skill tree there once — the directory is the same regardless of
|
|
38
|
+
# which CLI triggered the install.
|
|
39
|
+
AGENTS_SKILLS_DIR = Path.home() / ".agents" / "skills"
|
|
40
|
+
AGENTS_SKILLS_BINARIES = ("gemini", "codex")
|
|
41
|
+
|
|
28
42
|
|
|
29
43
|
def _find_plugin_root() -> Path | None:
|
|
30
44
|
"""Locate the plugin assets directory.
|
|
@@ -97,6 +111,16 @@ def check_plugin_version() -> list[str]:
|
|
|
97
111
|
if installed != __version__:
|
|
98
112
|
warnings.append(f"OpenCode skill is outdated (v{installed} vs CLI v{__version__}). Run 'tl setup opencode' to update.")
|
|
99
113
|
|
|
114
|
+
# Gemini / Codex (shared ~/.agents/skills/ target)
|
|
115
|
+
agents_version_file = AGENTS_SKILLS_DIR / ".tl-version"
|
|
116
|
+
if agents_version_file.exists():
|
|
117
|
+
installed = agents_version_file.read_text().strip()
|
|
118
|
+
if installed != __version__:
|
|
119
|
+
warnings.append(
|
|
120
|
+
f"Gemini/Codex skills are outdated (v{installed} vs CLI v{__version__}). "
|
|
121
|
+
f"Run 'tl setup gemini' or 'tl setup codex' to update."
|
|
122
|
+
)
|
|
123
|
+
|
|
100
124
|
return warnings
|
|
101
125
|
|
|
102
126
|
|
|
@@ -308,68 +332,95 @@ def _setup_noninteractive() -> None:
|
|
|
308
332
|
# --- OpenCode setup ---
|
|
309
333
|
|
|
310
334
|
|
|
311
|
-
def
|
|
312
|
-
"""Copy skills
|
|
335
|
+
def _install_skill_trees(plugin_root: Path, target_dir: Path) -> int:
|
|
336
|
+
"""Copy every `skills/<name>/` tree under `plugin_root` into `target_dir`.
|
|
313
337
|
|
|
314
|
-
|
|
338
|
+
Shared primitive used by every "external agent" install path
|
|
339
|
+
(OpenCode, Gemini, Codex) — each agent reads skills from a different
|
|
340
|
+
base directory, so we just parameterise on that. A `.tl-version`
|
|
341
|
+
stamp is written into the target so `check_plugin_version()` can
|
|
342
|
+
detect drift later. Returns the number of skills installed.
|
|
315
343
|
"""
|
|
316
344
|
count = 0
|
|
317
345
|
skills_src = plugin_root / "skills"
|
|
318
346
|
if skills_src.is_dir():
|
|
319
347
|
for skill_dir in skills_src.iterdir():
|
|
320
348
|
if skill_dir.is_dir() and (skill_dir / "SKILL.md").is_file():
|
|
321
|
-
dst =
|
|
349
|
+
dst = target_dir / skill_dir.name
|
|
322
350
|
if dst.exists():
|
|
323
351
|
shutil.rmtree(dst)
|
|
324
352
|
shutil.copytree(skill_dir, dst)
|
|
325
353
|
count += 1
|
|
354
|
+
if count > 0 or target_dir.exists():
|
|
355
|
+
target_dir.mkdir(parents=True, exist_ok=True)
|
|
356
|
+
(target_dir / ".tl-version").write_text(__version__)
|
|
326
357
|
return count
|
|
327
358
|
|
|
328
359
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
"""Install the TL CLI skills for OpenCode.
|
|
360
|
+
# Back-compat names — both delegate to the shared primitive. Kept so other
|
|
361
|
+
# modules that import them continue to work without changes.
|
|
362
|
+
def _install_opencode_skills(plugin_root: Path) -> int:
|
|
363
|
+
return _install_skill_trees(plugin_root, OPENCODE_SKILLS_DIR)
|
|
334
364
|
|
|
335
|
-
Copies skill files to ~/.config/opencode/skills/ so OpenCode's
|
|
336
|
-
agent can discover and use them automatically.
|
|
337
365
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
366
|
+
def _install_agents_skills(plugin_root: Path) -> int:
|
|
367
|
+
return _install_skill_trees(plugin_root, AGENTS_SKILLS_DIR)
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def _setup_external_agent(
|
|
371
|
+
*,
|
|
372
|
+
agent_label: str,
|
|
373
|
+
agent_binary: str,
|
|
374
|
+
command_name: str,
|
|
375
|
+
target_dir: Path,
|
|
376
|
+
post_install_lines: list[str] | None,
|
|
377
|
+
json_output: bool,
|
|
378
|
+
) -> None:
|
|
379
|
+
"""Shared body for the OpenCode / Gemini / Codex setup commands.
|
|
380
|
+
|
|
381
|
+
All three follow the same shape: copy skill trees into a target
|
|
382
|
+
directory, stamp a `.tl-version` file, print a status report.
|
|
383
|
+
Arguments customise the diagnostic text and the install target.
|
|
384
|
+
Auto-discovery between agents has been intentionally removed —
|
|
385
|
+
`tl update` is responsible for re-syncing every detected agent
|
|
386
|
+
after a self-upgrade; the per-agent setup commands stay scoped to
|
|
387
|
+
their one agent.
|
|
341
388
|
"""
|
|
389
|
+
plugin_root = _find_plugin_root()
|
|
390
|
+
|
|
342
391
|
if json_output:
|
|
343
|
-
result = {"cli_version": __version__}
|
|
344
|
-
plugin_root = _find_plugin_root()
|
|
392
|
+
result: dict = {"cli_version": __version__}
|
|
345
393
|
if plugin_root is None:
|
|
346
394
|
result["status"] = "error"
|
|
347
395
|
result["error"] = "Plugin assets not found"
|
|
348
396
|
print(json.dumps(result, indent=2))
|
|
349
397
|
raise SystemExit(1)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
(OPENCODE_SKILLS_DIR / ".tl-version").write_text(__version__)
|
|
398
|
+
result[f"{agent_binary}_detected"] = shutil.which(agent_binary) is not None
|
|
399
|
+
count = _install_skill_trees(plugin_root, target_dir)
|
|
353
400
|
result["skills_installed"] = count
|
|
401
|
+
result["install_dir"] = str(target_dir)
|
|
354
402
|
result["status"] = "ok"
|
|
355
403
|
print(json.dumps(result, indent=2))
|
|
356
404
|
return
|
|
357
405
|
|
|
358
406
|
console.print()
|
|
359
|
-
console.print(f"[bold]tl-cli[/bold] v{__version__} —
|
|
407
|
+
console.print(f"[bold]tl-cli[/bold] v{__version__} — {agent_label} Setup")
|
|
360
408
|
console.print()
|
|
361
409
|
|
|
362
|
-
# Check tl is on PATH
|
|
363
410
|
tl_bin = shutil.which("tl")
|
|
364
411
|
if tl_bin:
|
|
365
412
|
console.print(f" [green]✓[/green] tl CLI found: {tl_bin}")
|
|
366
413
|
else:
|
|
367
414
|
console.print(" [red]✗[/red] tl CLI not found on PATH")
|
|
368
|
-
console.print("
|
|
415
|
+
console.print(f" {agent_label}'s shell tool won't be able to run tl commands.")
|
|
369
416
|
console.print(" Install with: [cyan]pipx install git+https://github.com/ThoughtLeaders-io/thoughtleaders-cli.git[/cyan]")
|
|
370
417
|
|
|
371
|
-
|
|
372
|
-
|
|
418
|
+
agent_bin = shutil.which(agent_binary)
|
|
419
|
+
if agent_bin:
|
|
420
|
+
console.print(f" [green]✓[/green] {agent_binary} binary found: {agent_bin}")
|
|
421
|
+
else:
|
|
422
|
+
console.print(f" [yellow]![/yellow] {agent_binary} binary not found on PATH (installing skills anyway)")
|
|
423
|
+
|
|
373
424
|
if plugin_root is None:
|
|
374
425
|
console.print(" [red]✗[/red] Plugin assets not found")
|
|
375
426
|
console.print(" Try reinstalling: [cyan]pipx install --force git+https://github.com/ThoughtLeaders-io/thoughtleaders-cli.git[/cyan]")
|
|
@@ -377,23 +428,96 @@ def setup_opencode(
|
|
|
377
428
|
console.print(f" [green]✓[/green] Plugin assets found: {plugin_root}")
|
|
378
429
|
console.print()
|
|
379
430
|
|
|
380
|
-
# Install skills
|
|
381
431
|
console.print("[bold]Installing skills...[/bold]")
|
|
382
|
-
count =
|
|
432
|
+
count = _install_skill_trees(plugin_root, target_dir)
|
|
383
433
|
if count > 0:
|
|
384
|
-
console.print(f" [green]✓[/green] Installed {count} skill(s) to {
|
|
434
|
+
console.print(f" [green]✓[/green] Installed {count} skill(s) to {target_dir}/")
|
|
385
435
|
else:
|
|
386
436
|
console.print(" [yellow]![/yellow] No skills found to install")
|
|
387
437
|
raise SystemExit(1)
|
|
388
438
|
|
|
389
|
-
# Write version stamp
|
|
390
|
-
OPENCODE_SKILLS_DIR.mkdir(parents=True, exist_ok=True)
|
|
391
|
-
(OPENCODE_SKILLS_DIR / ".tl-version").write_text(__version__)
|
|
392
|
-
|
|
393
439
|
console.print()
|
|
394
440
|
console.print("[green]Setup complete![/green]")
|
|
395
441
|
console.print()
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
442
|
+
for line in post_install_lines or []:
|
|
443
|
+
console.print(line)
|
|
444
|
+
if post_install_lines:
|
|
445
|
+
console.print()
|
|
446
|
+
console.print(f"[dim]To update, run: tl setup {command_name}[/dim]")
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
@app.command("opencode")
|
|
450
|
+
def setup_opencode(
|
|
451
|
+
json_output: bool = typer.Option(False, "--json", help="JSON output (non-interactive)"),
|
|
452
|
+
) -> None:
|
|
453
|
+
"""Install the TL CLI skills for OpenCode.
|
|
454
|
+
|
|
455
|
+
Copies skill files to ~/.config/opencode/skills/ so OpenCode's
|
|
456
|
+
agent can discover and use them automatically.
|
|
457
|
+
|
|
458
|
+
Examples:
|
|
459
|
+
tl setup opencode
|
|
460
|
+
tl setup opencode --json
|
|
461
|
+
"""
|
|
462
|
+
_setup_external_agent(
|
|
463
|
+
agent_label="OpenCode",
|
|
464
|
+
agent_binary="opencode",
|
|
465
|
+
command_name="opencode",
|
|
466
|
+
target_dir=OPENCODE_SKILLS_DIR,
|
|
467
|
+
post_install_lines=[
|
|
468
|
+
"OpenCode will automatically discover the tl skill.",
|
|
469
|
+
"The agent can use it when you ask about sponsorships, deals, channels, or brands.",
|
|
470
|
+
],
|
|
471
|
+
json_output=json_output,
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
# --- Gemini / Codex setup (shared ~/.agents/skills/ target) ---
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
@app.command("gemini")
|
|
479
|
+
def setup_gemini(
|
|
480
|
+
json_output: bool = typer.Option(False, "--json", help="JSON output (non-interactive)"),
|
|
481
|
+
) -> None:
|
|
482
|
+
"""Install the TL CLI skills for the Gemini CLI.
|
|
483
|
+
|
|
484
|
+
Copies skill files to ~/.agents/skills/ so the Gemini CLI can
|
|
485
|
+
discover and use them automatically. Shares its install target with
|
|
486
|
+
`tl setup codex` — running either installs the same files.
|
|
487
|
+
|
|
488
|
+
Examples:
|
|
489
|
+
tl setup gemini
|
|
490
|
+
tl setup gemini --json
|
|
491
|
+
"""
|
|
492
|
+
_setup_external_agent(
|
|
493
|
+
agent_label="Gemini",
|
|
494
|
+
agent_binary="gemini",
|
|
495
|
+
command_name="gemini",
|
|
496
|
+
target_dir=AGENTS_SKILLS_DIR,
|
|
497
|
+
post_install_lines=None,
|
|
498
|
+
json_output=json_output,
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
@app.command("codex")
|
|
503
|
+
def setup_codex(
|
|
504
|
+
json_output: bool = typer.Option(False, "--json", help="JSON output (non-interactive)"),
|
|
505
|
+
) -> None:
|
|
506
|
+
"""Install the TL CLI skills for the Codex CLI.
|
|
507
|
+
|
|
508
|
+
Copies skill files to ~/.agents/skills/ so the Codex CLI can
|
|
509
|
+
discover and use them automatically. Shares its install target with
|
|
510
|
+
`tl setup gemini` — running either installs the same files.
|
|
511
|
+
|
|
512
|
+
Examples:
|
|
513
|
+
tl setup codex
|
|
514
|
+
tl setup codex --json
|
|
515
|
+
"""
|
|
516
|
+
_setup_external_agent(
|
|
517
|
+
agent_label="Codex",
|
|
518
|
+
agent_binary="codex",
|
|
519
|
+
command_name="codex",
|
|
520
|
+
target_dir=AGENTS_SKILLS_DIR,
|
|
521
|
+
post_install_lines=None,
|
|
522
|
+
json_output=json_output,
|
|
523
|
+
)
|
|
@@ -405,7 +405,12 @@ def _resync_integrations() -> None:
|
|
|
405
405
|
tl_bin = shutil.which("tl")
|
|
406
406
|
if not tl_bin:
|
|
407
407
|
return
|
|
408
|
-
for tool, binary in (
|
|
408
|
+
for tool, binary in (
|
|
409
|
+
("claude", "claude"),
|
|
410
|
+
("opencode", "opencode"),
|
|
411
|
+
("gemini", "gemini"),
|
|
412
|
+
("codex", "codex"),
|
|
413
|
+
):
|
|
409
414
|
if not shutil.which(binary):
|
|
410
415
|
continue
|
|
411
416
|
print(f"[tl-cli] re-syncing {tool} skills…", file=sys.stderr)
|
|
File without changes
|
{thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/.github/workflows/python-publish.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl/references/business-glossary.md
RENAMED
|
File without changes
|
{thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl/references/elasticsearch-schema.md
RENAMED
|
File without changes
|
{thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl/references/firebolt-schema.md
RENAMED
|
File without changes
|
{thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/skills/tl/references/postgres-schema.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{thoughtleaders_cli-0.6.39 → thoughtleaders_cli-0.6.41}/src/tl_cli/commands/_comments_common.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|