linkup-cli 0.1.0__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.
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: linkup-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official CLI for Linkup - AI-powered web search
|
|
5
|
+
Project-URL: Homepage, https://linkup.so
|
|
6
|
+
Project-URL: Documentation, https://docs.linkup.so
|
|
7
|
+
Project-URL: Repository, https://github.com/LinkupPlatform/linkup-cli
|
|
8
|
+
Project-URL: Issues, https://github.com/LinkupPlatform/linkup-cli/issues
|
|
9
|
+
Author-email: Linkup <support@linkup.so>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
Keywords: ai,cli,linkup,search,web-search
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Requires-Dist: linkup-sdk>=0.2.0
|
|
26
|
+
Requires-Dist: rich>=13.0.0
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# Linkup CLI
|
|
30
|
+
|
|
31
|
+
Official command-line interface for [Linkup](https://linkup.so) - AI-powered web search.
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install linkup-cli
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
1. Get your API key at [app.linkup.so](https://app.linkup.so)
|
|
42
|
+
|
|
43
|
+
2. Set your API key:
|
|
44
|
+
```bash
|
|
45
|
+
export LINKUP_API_KEY="your-api-key"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
3. Search:
|
|
49
|
+
```bash
|
|
50
|
+
linkup search "What is the capital of France?"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
### Search
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Basic search
|
|
59
|
+
linkup search "your query"
|
|
60
|
+
|
|
61
|
+
# Deep search (more thorough, better for complex queries)
|
|
62
|
+
linkup search "complex research topic" --deep
|
|
63
|
+
|
|
64
|
+
# Get raw search results instead of AI answer
|
|
65
|
+
linkup search "python tutorials" --results
|
|
66
|
+
|
|
67
|
+
# Short form
|
|
68
|
+
linkup s "your query" -d
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Fetch
|
|
72
|
+
|
|
73
|
+
Extract content from any URL:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
linkup fetch "https://example.com"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Configuration
|
|
80
|
+
|
|
81
|
+
Check your configuration:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
linkup config
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Options
|
|
88
|
+
|
|
89
|
+
| Flag | Short | Description |
|
|
90
|
+
|------|-------|-------------|
|
|
91
|
+
| `--deep` | `-d` | Use deep search for complex queries |
|
|
92
|
+
| `--results` | `-r` | Return raw search results |
|
|
93
|
+
| `--version` | `-V` | Show version |
|
|
94
|
+
| `--help` | `-h` | Show help |
|
|
95
|
+
|
|
96
|
+
## Environment Variables
|
|
97
|
+
|
|
98
|
+
| Variable | Description |
|
|
99
|
+
|----------|-------------|
|
|
100
|
+
| `LINKUP_API_KEY` | Your Linkup API key (required) |
|
|
101
|
+
|
|
102
|
+
## Examples
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Quick facts
|
|
106
|
+
linkup search "population of tokyo"
|
|
107
|
+
|
|
108
|
+
# Research
|
|
109
|
+
linkup search "latest developments in quantum computing" --deep
|
|
110
|
+
|
|
111
|
+
# Get sources
|
|
112
|
+
linkup search "best python web frameworks" --results
|
|
113
|
+
|
|
114
|
+
# Extract article content
|
|
115
|
+
linkup fetch "https://example.com/article"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Links
|
|
119
|
+
|
|
120
|
+
- [Linkup Website](https://linkup.so)
|
|
121
|
+
- [Documentation](https://docs.linkup.so)
|
|
122
|
+
- [Get API Key](https://app.linkup.so)
|
|
123
|
+
- [Python SDK](https://github.com/LinkupPlatform/linkup-python-sdk)
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
MIT
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Linkup CLI
|
|
2
|
+
|
|
3
|
+
Official command-line interface for [Linkup](https://linkup.so) - AI-powered web search.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install linkup-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
1. Get your API key at [app.linkup.so](https://app.linkup.so)
|
|
14
|
+
|
|
15
|
+
2. Set your API key:
|
|
16
|
+
```bash
|
|
17
|
+
export LINKUP_API_KEY="your-api-key"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
3. Search:
|
|
21
|
+
```bash
|
|
22
|
+
linkup search "What is the capital of France?"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Search
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Basic search
|
|
31
|
+
linkup search "your query"
|
|
32
|
+
|
|
33
|
+
# Deep search (more thorough, better for complex queries)
|
|
34
|
+
linkup search "complex research topic" --deep
|
|
35
|
+
|
|
36
|
+
# Get raw search results instead of AI answer
|
|
37
|
+
linkup search "python tutorials" --results
|
|
38
|
+
|
|
39
|
+
# Short form
|
|
40
|
+
linkup s "your query" -d
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Fetch
|
|
44
|
+
|
|
45
|
+
Extract content from any URL:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
linkup fetch "https://example.com"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Configuration
|
|
52
|
+
|
|
53
|
+
Check your configuration:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
linkup config
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Options
|
|
60
|
+
|
|
61
|
+
| Flag | Short | Description |
|
|
62
|
+
|------|-------|-------------|
|
|
63
|
+
| `--deep` | `-d` | Use deep search for complex queries |
|
|
64
|
+
| `--results` | `-r` | Return raw search results |
|
|
65
|
+
| `--version` | `-V` | Show version |
|
|
66
|
+
| `--help` | `-h` | Show help |
|
|
67
|
+
|
|
68
|
+
## Environment Variables
|
|
69
|
+
|
|
70
|
+
| Variable | Description |
|
|
71
|
+
|----------|-------------|
|
|
72
|
+
| `LINKUP_API_KEY` | Your Linkup API key (required) |
|
|
73
|
+
|
|
74
|
+
## Examples
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Quick facts
|
|
78
|
+
linkup search "population of tokyo"
|
|
79
|
+
|
|
80
|
+
# Research
|
|
81
|
+
linkup search "latest developments in quantum computing" --deep
|
|
82
|
+
|
|
83
|
+
# Get sources
|
|
84
|
+
linkup search "best python web frameworks" --results
|
|
85
|
+
|
|
86
|
+
# Extract article content
|
|
87
|
+
linkup fetch "https://example.com/article"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Links
|
|
91
|
+
|
|
92
|
+
- [Linkup Website](https://linkup.so)
|
|
93
|
+
- [Documentation](https://docs.linkup.so)
|
|
94
|
+
- [Get API Key](https://app.linkup.so)
|
|
95
|
+
- [Python SDK](https://github.com/LinkupPlatform/linkup-python-sdk)
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
MIT
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "linkup-cli"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Official CLI for Linkup - AI-powered web search"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Linkup", email = "support@linkup.so" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["linkup", "cli", "search", "ai", "web-search"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.9",
|
|
24
|
+
"Programming Language :: Python :: 3.10",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Programming Language :: Python :: 3.13",
|
|
28
|
+
"Topic :: Internet :: WWW/HTTP :: Indexing/Search",
|
|
29
|
+
]
|
|
30
|
+
dependencies = [
|
|
31
|
+
"linkup-sdk>=0.2.0",
|
|
32
|
+
"rich>=13.0.0",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://linkup.so"
|
|
37
|
+
Documentation = "https://docs.linkup.so"
|
|
38
|
+
Repository = "https://github.com/LinkupPlatform/linkup-cli"
|
|
39
|
+
Issues = "https://github.com/LinkupPlatform/linkup-cli/issues"
|
|
40
|
+
|
|
41
|
+
[project.scripts]
|
|
42
|
+
linkup = "linkup_cli.cli:main"
|
|
43
|
+
|
|
44
|
+
[tool.hatch.build.targets.wheel]
|
|
45
|
+
packages = ["src/linkup_cli"]
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"""Linkup CLI - Search the web with AI from your terminal."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
def get_client():
|
|
8
|
+
"""Initialize and return the Linkup client."""
|
|
9
|
+
api_key = os.environ.get("LINKUP_API_KEY")
|
|
10
|
+
if not api_key:
|
|
11
|
+
print("Error: LINKUP_API_KEY environment variable not set")
|
|
12
|
+
print("Get your API key at https://app.linkup.so")
|
|
13
|
+
print("\nSet it with: export LINKUP_API_KEY='your-key'")
|
|
14
|
+
sys.exit(1)
|
|
15
|
+
|
|
16
|
+
from linkup import LinkupClient
|
|
17
|
+
return LinkupClient(api_key=api_key)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def cmd_search(args):
|
|
21
|
+
"""Execute a search query."""
|
|
22
|
+
from rich.console import Console
|
|
23
|
+
from rich.markdown import Markdown
|
|
24
|
+
from rich.panel import Panel
|
|
25
|
+
|
|
26
|
+
console = Console()
|
|
27
|
+
client = get_client()
|
|
28
|
+
|
|
29
|
+
query = " ".join(args.query)
|
|
30
|
+
if not query:
|
|
31
|
+
console.print("[red]Error: No query provided[/red]")
|
|
32
|
+
sys.exit(1)
|
|
33
|
+
|
|
34
|
+
with console.status(f"[bold blue]Searching...[/bold blue]"):
|
|
35
|
+
response = client.search(
|
|
36
|
+
query=query,
|
|
37
|
+
depth="deep" if args.deep else "standard",
|
|
38
|
+
output_type="searchResults" if args.results else "sourcedAnswer",
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
if args.results:
|
|
42
|
+
# Display search results
|
|
43
|
+
for i, result in enumerate(response.results, 1):
|
|
44
|
+
console.print(f"\n[bold cyan]{i}. {result.name}[/bold cyan]")
|
|
45
|
+
console.print(f" [dim]{result.url}[/dim]")
|
|
46
|
+
if result.content:
|
|
47
|
+
snippet = result.content[:300] + "..." if len(result.content) > 300 else result.content
|
|
48
|
+
console.print(f" {snippet}")
|
|
49
|
+
else:
|
|
50
|
+
# Display sourced answer
|
|
51
|
+
console.print()
|
|
52
|
+
console.print(Markdown(response.answer))
|
|
53
|
+
|
|
54
|
+
if hasattr(response, "sources") and response.sources:
|
|
55
|
+
console.print("\n[bold]Sources:[/bold]")
|
|
56
|
+
for src in response.sources[:5]:
|
|
57
|
+
console.print(f" [dim]•[/dim] [link={src.url}]{src.name}[/link]")
|
|
58
|
+
|
|
59
|
+
console.print()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def cmd_fetch(args):
|
|
63
|
+
"""Fetch and extract content from a URL."""
|
|
64
|
+
from rich.console import Console
|
|
65
|
+
from rich.markdown import Markdown
|
|
66
|
+
|
|
67
|
+
console = Console()
|
|
68
|
+
client = get_client()
|
|
69
|
+
|
|
70
|
+
with console.status(f"[bold blue]Fetching {args.url}...[/bold blue]"):
|
|
71
|
+
response = client.fetch(url=args.url)
|
|
72
|
+
|
|
73
|
+
console.print()
|
|
74
|
+
console.print(Markdown(response.content))
|
|
75
|
+
console.print()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def cmd_config(args):
|
|
79
|
+
"""Show or set configuration."""
|
|
80
|
+
from rich.console import Console
|
|
81
|
+
from rich.table import Table
|
|
82
|
+
|
|
83
|
+
console = Console()
|
|
84
|
+
|
|
85
|
+
table = Table(title="Linkup CLI Configuration")
|
|
86
|
+
table.add_column("Setting", style="cyan")
|
|
87
|
+
table.add_column("Value", style="green")
|
|
88
|
+
|
|
89
|
+
api_key = os.environ.get("LINKUP_API_KEY", "")
|
|
90
|
+
masked_key = f"{api_key[:8]}...{api_key[-4:]}" if len(api_key) > 12 else "(not set)"
|
|
91
|
+
|
|
92
|
+
table.add_row("API Key", masked_key)
|
|
93
|
+
table.add_row("API Key Set", "Yes" if api_key else "[red]No[/red]")
|
|
94
|
+
|
|
95
|
+
console.print()
|
|
96
|
+
console.print(table)
|
|
97
|
+
console.print()
|
|
98
|
+
|
|
99
|
+
if not api_key:
|
|
100
|
+
console.print("[yellow]To set your API key:[/yellow]")
|
|
101
|
+
console.print(" export LINKUP_API_KEY='your-key'")
|
|
102
|
+
console.print("\nGet your API key at: [link=https://app.linkup.so]https://app.linkup.so[/link]")
|
|
103
|
+
console.print()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def main():
|
|
107
|
+
"""Main CLI entry point."""
|
|
108
|
+
parser = argparse.ArgumentParser(
|
|
109
|
+
prog="linkup",
|
|
110
|
+
description="Linkup CLI - AI-powered web search from your terminal",
|
|
111
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
112
|
+
epilog="""
|
|
113
|
+
Examples:
|
|
114
|
+
linkup search "What is the capital of France?"
|
|
115
|
+
linkup search "Latest AI news" --deep
|
|
116
|
+
linkup search "Python tutorials" --results
|
|
117
|
+
linkup fetch "https://example.com"
|
|
118
|
+
linkup config
|
|
119
|
+
|
|
120
|
+
Get your API key at: https://app.linkup.so
|
|
121
|
+
Documentation: https://docs.linkup.so
|
|
122
|
+
""",
|
|
123
|
+
)
|
|
124
|
+
parser.add_argument(
|
|
125
|
+
"--version", "-V", action="version", version="%(prog)s 0.1.0"
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
|
129
|
+
|
|
130
|
+
# Search command
|
|
131
|
+
search_parser = subparsers.add_parser(
|
|
132
|
+
"search", aliases=["s"], help="Search the web"
|
|
133
|
+
)
|
|
134
|
+
search_parser.add_argument("query", nargs="*", help="Search query")
|
|
135
|
+
search_parser.add_argument(
|
|
136
|
+
"--deep", "-d", action="store_true",
|
|
137
|
+
help="Use deep search for complex queries"
|
|
138
|
+
)
|
|
139
|
+
search_parser.add_argument(
|
|
140
|
+
"--results", "-r", action="store_true",
|
|
141
|
+
help="Return raw search results instead of AI answer"
|
|
142
|
+
)
|
|
143
|
+
search_parser.set_defaults(func=cmd_search)
|
|
144
|
+
|
|
145
|
+
# Fetch command
|
|
146
|
+
fetch_parser = subparsers.add_parser(
|
|
147
|
+
"fetch", aliases=["f"], help="Fetch and extract content from a URL"
|
|
148
|
+
)
|
|
149
|
+
fetch_parser.add_argument("url", help="URL to fetch")
|
|
150
|
+
fetch_parser.set_defaults(func=cmd_fetch)
|
|
151
|
+
|
|
152
|
+
# Config command
|
|
153
|
+
config_parser = subparsers.add_parser(
|
|
154
|
+
"config", aliases=["c"], help="Show configuration"
|
|
155
|
+
)
|
|
156
|
+
config_parser.set_defaults(func=cmd_config)
|
|
157
|
+
|
|
158
|
+
# Parse args
|
|
159
|
+
args = parser.parse_args()
|
|
160
|
+
|
|
161
|
+
# Handle no command - default to search if args look like a query
|
|
162
|
+
if args.command is None:
|
|
163
|
+
# Check if there are extra args that might be a query
|
|
164
|
+
if len(sys.argv) > 1 and not sys.argv[1].startswith("-"):
|
|
165
|
+
# Treat as implicit search
|
|
166
|
+
sys.argv.insert(1, "search")
|
|
167
|
+
args = parser.parse_args()
|
|
168
|
+
else:
|
|
169
|
+
parser.print_help()
|
|
170
|
+
sys.exit(0)
|
|
171
|
+
|
|
172
|
+
# Execute command
|
|
173
|
+
if hasattr(args, "func"):
|
|
174
|
+
args.func(args)
|
|
175
|
+
else:
|
|
176
|
+
parser.print_help()
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
if __name__ == "__main__":
|
|
180
|
+
main()
|