searchxng 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # SearchXNG CLI
2
+
3
+ A command-line interface for querying a [SearchXNG](https://docs.searxng.org/) instance.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g searchxng
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ searchxng "your search query here" [options]
15
+ ```
16
+
17
+ ### Options:
18
+ - `-e, --endpoint <url>`: The SearchXNG instance URL (defaults to `http://localhost:8080/` or `SEARCHXNG_URL` env var)
19
+ - `-l, --language <lang>`: Language to search in (defaults to `en`)
20
+ - `-c, --categories <categories>`: Comma-separated list of categories (e.g. `news,science`)
21
+ - `-m, --max-results <number>`: Maximum number of results to return (defaults to `5`)
22
+ - `-j, --json`: Output raw JSON instead of formatted text
23
+
24
+ ### Examples:
25
+ ```bash
26
+ # Basic search with a specific endpoint
27
+ searchxng "cool new restaurants in orange county" --endpoint "http://192.168.4.4:8081/"
28
+
29
+ # Search in specific language
30
+ searchxng "best restaurants" -e "http://192.168.4.4:8081/" -l "es"
31
+
32
+ # Search with specific categories
33
+ searchxng "latest AI news" -e "http://192.168.4.4:8081/" -c "news,science"
34
+ ```
35
+
36
+ ## Configuration
37
+
38
+ You can also omit the `--endpoint` parameter if you export the `SEARCHXNG_URL` environment variable in your session:
39
+
40
+ ```bash
41
+ export SEARCHXNG_URL="http://192.168.4.4:8081/"
42
+ searchxng "cool new restaurants in orange county"
43
+ ```
44
+
45
+ ### Troubleshooting: 403 Forbidden Error
46
+ If you encounter a `403 Forbidden` error when running a search, it is likely because SearchXNG disables JSON API requests by default for security/privacy. To fix this, enable the `json` format in your SearchXNG's `settings.yml` file:
47
+
48
+ ```yaml
49
+ search:
50
+ formats:
51
+ - html
52
+ - json
53
+ ```
54
+ Restart your SearchXNG container or service after updating the settings.
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { Command } = require("commander");
4
+
5
+ const program = new Command();
6
+
7
+ program
8
+ .name("searchxng")
9
+ .description("CLI to query a local or remote SearchXNG instance")
10
+ .version("1.0.0");
11
+
12
+ program
13
+ .argument("<query>", "The search query")
14
+ .option("-e, --endpoint <url>", "The SearchXNG instance URL", process.env.SEARCHXNG_URL || "http://localhost:8080/")
15
+ .option("-l, --language <lang>", "Language to search in", "en")
16
+ .option("-c, --categories <categories>", "Comma-separated list of categories (e.g. news,science)")
17
+ .option("-m, --max-results <number>", "Maximum number of results to return", "5")
18
+ .option("-j, --json", "Output raw JSON instead of formatted text")
19
+ .action(async (query, options) => {
20
+ try {
21
+ let endpoint = options.endpoint;
22
+ if (!endpoint.startsWith("http://") && !endpoint.startsWith("https://")) {
23
+ endpoint = "http://" + endpoint;
24
+ }
25
+
26
+ const baseUrl = endpoint.endsWith("/") ? endpoint : `${endpoint}/`;
27
+ const url = new URL("search", baseUrl);
28
+
29
+ url.searchParams.set("q", query);
30
+ url.searchParams.set("format", "json");
31
+ url.searchParams.set("language", options.language);
32
+
33
+ if (options.categories) {
34
+ url.searchParams.set("categories", options.categories);
35
+ }
36
+
37
+ const controller = new AbortController();
38
+ const timeoutId = setTimeout(() => controller.abort(), 15000); // 15 second timeout
39
+
40
+ const response = await fetch(url.toString(), { signal: controller.signal });
41
+ clearTimeout(timeoutId);
42
+
43
+ if (!response.ok) {
44
+ console.error(`SearchXNG API returned status ${response.status}`);
45
+ process.exit(1);
46
+ }
47
+
48
+ const data = await response.json();
49
+
50
+ const results = data.results || [];
51
+
52
+ let limit = parseInt(options.maxResults, 10);
53
+ if (isNaN(limit) || limit <= 0) limit = 5;
54
+
55
+ const topResults = results.slice(0, limit);
56
+
57
+ if (options.json) {
58
+ console.log(JSON.stringify(topResults, null, 2));
59
+ return;
60
+ }
61
+
62
+ if (topResults.length === 0) {
63
+ console.log("No results found.");
64
+ return;
65
+ }
66
+
67
+ const formatted = topResults.map((r, i) => {
68
+ return `${i + 1}. ${r.title}\n URL: ${r.url}\n Snippet: ${r.content || r.snippet || ""}`;
69
+ }).join("\n\n");
70
+
71
+ console.log(formatted);
72
+ } catch (error) {
73
+ console.error(`Failed to search: ${error.message}`);
74
+ process.exit(1);
75
+ }
76
+ });
77
+
78
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "searchxng",
3
+ "version": "1.0.0",
4
+ "description": "A command-line interface for querying a SearchXNG instance.",
5
+ "bin": {
6
+ "searchxng": "./bin/searchxng.js"
7
+ },
8
+ "files": [
9
+ "bin",
10
+ "README.md"
11
+ ],
12
+ "scripts": {
13
+ "test": "echo \"Error: no test specified\" && exit 1"
14
+ },
15
+ "keywords": [
16
+ "searchxng",
17
+ "search",
18
+ "cli"
19
+ ],
20
+ "author": "chrisb",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/chrisb/searchxng-cli.git",
24
+ "directory": "packages/cli"
25
+ },
26
+ "license": "MIT",
27
+ "engines": {
28
+ "node": ">=20.0.0"
29
+ },
30
+ "dependencies": {
31
+ "commander": "^14.0.3"
32
+ }
33
+ }