@koolink/koolink 1.0.1
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/LICENSE +21 -0
- package/README.md +83 -0
- package/bin/koolink.js +142 -0
- package/package.json +39 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 KooLink
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# koolink
|
|
2
|
+
|
|
3
|
+
Shorten any URL to a clean `kool.ink/xyz` link from your terminal. **Free, unlimited, no signup.** AI-agent ready.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx @koolink/koolink https://example.com/very/long/path
|
|
7
|
+
# → https://kool.ink/abc123
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# one-off (no install)
|
|
14
|
+
npx @koolink/koolink https://example.com
|
|
15
|
+
|
|
16
|
+
# or install globally
|
|
17
|
+
npm install -g @koolink/koolink
|
|
18
|
+
koolink https://example.com
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Shorten a URL (prints the short link, copies to clipboard on desktop)
|
|
25
|
+
koolink https://example.com/very/long/path
|
|
26
|
+
|
|
27
|
+
# Shorten from stdin (great for piping)
|
|
28
|
+
echo "https://example.com" | koolink
|
|
29
|
+
|
|
30
|
+
# Shorten a batch
|
|
31
|
+
cat urls.txt | xargs -I{} koolink {}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
| Flag | Description |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `--help` / `-h` | Show help |
|
|
37
|
+
| `--version` / `-v` | Show version |
|
|
38
|
+
|
|
39
|
+
## Install as an MCP server
|
|
40
|
+
|
|
41
|
+
Point any MCP client (Claude Desktop, Cursor, Windsurf, etc.) at the hosted MCP server at `https://mcp.kool.ink` — no API key required for anonymous shortening.
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"mcpServers": {
|
|
46
|
+
"koolink": {
|
|
47
|
+
"url": "https://mcp.kool.ink"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Tools
|
|
54
|
+
|
|
55
|
+
This server exposes the following MCP tools:
|
|
56
|
+
|
|
57
|
+
| Tool | Description | Input |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `shorten_url` | Shorten a long URL and return a compact kool.ink short link. | `{ "url": "<long-url>" }` |
|
|
60
|
+
|
|
61
|
+
## Why KooLink
|
|
62
|
+
|
|
63
|
+
- **Free forever** — no account, no credit card, no limits
|
|
64
|
+
- **Clean, memorable URLs** — `kool.ink/xyz`, not `bit.ly/4xdK9qZ`
|
|
65
|
+
- **AI-agent ready** — same service over MCP at `https://mcp.kool.ink`, or the REST API
|
|
66
|
+
- **Analytics** — every link is click-tracked with bot traffic filtered out
|
|
67
|
+
- **Creator Earning Programme** — as traffic grows, you earn
|
|
68
|
+
|
|
69
|
+
## API
|
|
70
|
+
|
|
71
|
+
The CLI calls the public anonymous endpoint:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
curl -X POST https://kool.ink/api/links \
|
|
75
|
+
-H "Content-Type: application/json" \
|
|
76
|
+
-d '{"url":"https://example.com"}'
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
For AI agents, use the MCP server at `https://mcp.kool.ink` (no API key needed for anonymous shortening).
|
|
80
|
+
|
|
81
|
+
## License
|
|
82
|
+
|
|
83
|
+
MIT
|
package/bin/koolink.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* koolink — shorten any URL to a clean kool.ink link from your terminal.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* koolink <url> Shorten a URL
|
|
7
|
+
* echo <url> | koolink Shorten from stdin
|
|
8
|
+
* koolink --help Show help
|
|
9
|
+
* koolink --version Show version
|
|
10
|
+
*
|
|
11
|
+
* Free, unlimited, no signup. Uses the public anonymous kool.ink API.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const API_URL = "https://kool.ink/api/links";
|
|
15
|
+
const SITE_URL = "https://kool.ink";
|
|
16
|
+
|
|
17
|
+
// Prevent self-shortening: never shorten a link that already points at kool.ink.
|
|
18
|
+
function isKoolinkUrl(url) {
|
|
19
|
+
try {
|
|
20
|
+
const u = new URL(url);
|
|
21
|
+
return /(^|\.)kool\.ink$/i.test(u.hostname) || /(^|\.)kool\.ink:/i.test(u.hostname);
|
|
22
|
+
} catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isValidUrl(url) {
|
|
28
|
+
try {
|
|
29
|
+
const u = new URL(url);
|
|
30
|
+
return u.protocol === "http:" || u.protocol === "https:";
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function shorten(url) {
|
|
37
|
+
const res = await fetch(API_URL, {
|
|
38
|
+
method: "POST",
|
|
39
|
+
headers: { "Content-Type": "application/json" },
|
|
40
|
+
body: JSON.stringify({ url }),
|
|
41
|
+
});
|
|
42
|
+
if (!res.ok) {
|
|
43
|
+
let msg = `API error ${res.status}`;
|
|
44
|
+
try {
|
|
45
|
+
const j = await res.json();
|
|
46
|
+
if (j.error) msg = j.error;
|
|
47
|
+
else if (j.message) msg = j.message;
|
|
48
|
+
} catch {}
|
|
49
|
+
throw new Error(msg);
|
|
50
|
+
}
|
|
51
|
+
const data = await res.json();
|
|
52
|
+
return data.shortUrl || data.url || API_URL;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function copy(text) {
|
|
56
|
+
// Best-effort: copy to clipboard if available (not on all platforms/CI).
|
|
57
|
+
if (!process.stdout.isTTY) return;
|
|
58
|
+
try {
|
|
59
|
+
const { execSync } = require("child_process");
|
|
60
|
+
if (process.platform === "darwin") execSync("pbcopy", { input: text });
|
|
61
|
+
else if (process.platform === "win32") execSync("clip", { input: text });
|
|
62
|
+
else if (process.platform === "linux") {
|
|
63
|
+
try { execSync("xclip", { input: text }, { stdio: "ignore" }); }
|
|
64
|
+
catch { try { execSync("xsel -b", { input: text }, { stdio: "ignore" }); } catch {} }
|
|
65
|
+
}
|
|
66
|
+
} catch {}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function main() {
|
|
70
|
+
const args = process.argv.slice(2);
|
|
71
|
+
|
|
72
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
73
|
+
console.log(`koolink — shorten any URL to a clean kool.ink link
|
|
74
|
+
|
|
75
|
+
Usage:
|
|
76
|
+
koolink <url> Shorten a URL
|
|
77
|
+
echo <url> | koolink Shorten from stdin
|
|
78
|
+
koolink --help Show this help
|
|
79
|
+
koolink --version Show version
|
|
80
|
+
|
|
81
|
+
Examples:
|
|
82
|
+
koolink https://example.com/very-long/path
|
|
83
|
+
echo "https://example.com" | koolink
|
|
84
|
+
cat urls.txt | xargs -I{} koolink {}
|
|
85
|
+
|
|
86
|
+
Free, unlimited, no signup. AI-agent ready: https://mcp.kool.ink`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (args.includes("--version") || args.includes("-v")) {
|
|
91
|
+
const pkg = require("../package.json");
|
|
92
|
+
console.log(pkg.version);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Resolve the URL: first non-flag arg, else stdin.
|
|
97
|
+
// Reject the known info flags first so "koolink --help" etc. still work.
|
|
98
|
+
let url = args.find((a) => !a.startsWith("-"));
|
|
99
|
+
if (!url) {
|
|
100
|
+
// Read from stdin (piped).
|
|
101
|
+
const stdin = await new Promise((resolve) => {
|
|
102
|
+
let buf = "";
|
|
103
|
+
process.stdin.setEncoding("utf8");
|
|
104
|
+
process.stdin.on("data", (d) => (buf += d));
|
|
105
|
+
process.stdin.on("end", () => resolve(buf.trim()));
|
|
106
|
+
});
|
|
107
|
+
url = stdin.split(/\s+/).find((s) => s.startsWith("http"));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (!url) {
|
|
111
|
+
console.error("Error: no URL provided. Usage: koolink <url> (or pipe: echo <url> | koolink)");
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!isValidUrl(url)) {
|
|
116
|
+
console.error(`Error: "${url}" is not a valid http(s) URL.`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (isKoolinkUrl(url)) {
|
|
121
|
+
console.error(`Error: "${url}" already points at kool.ink. Nothing to shorten.`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const short = await shorten(url);
|
|
127
|
+
console.log(short);
|
|
128
|
+
await copy(short);
|
|
129
|
+
if (process.stdout.isTTY) {
|
|
130
|
+
process.stderr.write(`\n✓ Copied to clipboard → ${short}\n`);
|
|
131
|
+
process.stderr.write(` (free, unlimited, no signup · ${SITE_URL})\n`);
|
|
132
|
+
}
|
|
133
|
+
} catch (e) {
|
|
134
|
+
console.error(`Error: ${e.message}`);
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
main().catch((e) => {
|
|
140
|
+
console.error(`Error: ${e.message}`);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@koolink/koolink",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Shorten any URL to a clean kool.ink link from your terminal. Free, unlimited, no signup. AI-agent ready.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"koolink": "./bin/koolink.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin"
|
|
10
|
+
],
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=16"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"url-shortener",
|
|
16
|
+
"shorten",
|
|
17
|
+
"short-link",
|
|
18
|
+
"shorturl",
|
|
19
|
+
"bitly",
|
|
20
|
+
"tinyurl",
|
|
21
|
+
"koolink",
|
|
22
|
+
"mcp",
|
|
23
|
+
"ai-agent",
|
|
24
|
+
"cli"
|
|
25
|
+
],
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"author": "KooLink",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/KooLink/koolink-cli.git"
|
|
31
|
+
},
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/KooLink/koolink-cli/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://kool.ink",
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
}
|
|
39
|
+
}
|