feat: initial open-source project structure

Agent Skill for searching and downloading torrents via TorrentClaw.
Includes SKILL.md with OpenClaw metadata, bash scripts for torrent
client detection, CONTRIBUTING.md, CHANGELOG.md, CI/CD with GitHub
Actions (shellcheck + conventional commits), lefthook git hooks,
Makefile, and .editorconfig.
This commit is contained in:
Deivid Soto 2026-02-13 18:40:25 +01:00
parent b0c4fc2e21
commit 98c550feb0
14 changed files with 1096 additions and 0 deletions

19
.editorconfig Normal file
View file

@ -0,0 +1,19 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
[*.sh]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab

53
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,53 @@
name: CI
on:
pull_request:
branches: [main]
push:
branches: [main]
permissions:
contents: read
jobs:
lint-commits:
name: Lint commits
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Validate conventional commits
run: |
base="${{ github.event.pull_request.base.sha }}"
head="${{ github.event.pull_request.head.sha }}"
pattern='^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?(!)?: .{1,}$'
failed=0
while IFS= read -r msg; do
first_line=$(echo "$msg" | head -1)
if ! echo "$first_line" | grep -qE "$pattern"; then
echo "FAIL: $first_line"
failed=1
fi
done < <(git log --format="%s" "$base".."$head")
if [ "$failed" -eq 1 ]; then
echo ""
echo "Some commits do not follow Conventional Commits format."
echo "Expected: <type>[scope][!]: <description>"
echo "See: https://www.conventionalcommits.org/"
exit 1
fi
echo "All commits follow Conventional Commits format."
lint-scripts:
name: Lint shell scripts
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run ShellCheck
run: shellcheck scripts/*.sh

23
.gitignore vendored Normal file
View file

@ -0,0 +1,23 @@
# IDE
.idea/
.vscode/
*.swp
*.swo
*~
# OS
.DS_Store
Thumbs.db
desktop.ini
# Temp
/tmp/
*.tmp
# Lefthook
lefthook-local.yml
.lefthookrc.local
# Environment
.env
.env.local

1
.lefthookrc Normal file
View file

@ -0,0 +1 @@
command -v shellcheck >/dev/null 2>&1 || export PATH="/usr/local/bin:$HOME/.local/bin:$PATH"

17
CHANGELOG.md Normal file
View file

@ -0,0 +1,17 @@
# Changelog
All notable changes to this project will be documented in this file.
## [0.1.13] - 2026-02-13
### Features
- Search movies and TV shows across 12+ torrent sources
- Filter by quality (480p-2160p), genre, year, rating, language, season/episode
- API key authentication with tiered rate limits
- Quality scoring (0-100) based on resolution, codec, seeders, source trust
- Multi-language support (11 languages with accent-insensitive search)
- Detect installed torrent clients (Transmission, aria2)
- Add magnet links directly to torrent clients
- Download .torrent files or copy magnet links
- OS-specific installation guides for torrent clients

65
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,65 @@
# Contributing to torrentclaw-skill
Thanks for your interest in contributing! Here's how you can help.
## Getting Started
1. Fork the repository
2. Clone your fork: `git clone https://github.com/<your-user>/torrentclaw-skill.git`
3. Install dev tools and git hooks:
```bash
make install-tools
make hooks
```
4. Create a branch: `git checkout -b feat/my-feature`
5. Make your changes
6. Lint locally: `make lint`
7. Commit with a clear message (see below) — the commit-msg hook will validate the format
8. Push and open a Pull Request
## Requirements
- Bash 4+
- [shellcheck](https://github.com/koalaman/shellcheck) (installed via your package manager)
- [lefthook](https://github.com/evilmartians/lefthook) (installed via your package manager)
## Commit Messages
Commits are validated automatically by a git hook. We follow [Conventional Commits](https://www.conventionalcommits.org/):
```
<type>[optional scope][!]: <description>
```
Valid types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`
Examples:
```
feat: add qBittorrent client detection
fix(detect): correct aria2 daemon check on macOS
docs: update API reference with new endpoints
chore: update shellcheck to latest version
feat!: redesign install guide output format
```
## Code Style
- All shell scripts must pass `shellcheck`
- Use `#!/usr/bin/env bash` as the shebang
- Use `set -euo pipefail` at the top of every script
- Keep functions focused and small
- Add comments only where the logic isn't self-evident
## Reporting Bugs
Open an issue with:
- What you expected to happen
- What actually happened
- Steps to reproduce
- Your OS and bash version
## License
By contributing, you agree that your contributions will be licensed under the project's [MIT License](LICENSE).

23
Makefile Normal file
View file

@ -0,0 +1,23 @@
.PHONY: lint shellcheck version install-tools hooks
# Lint shell scripts
shellcheck:
shellcheck scripts/*.sh
# Lint everything
lint: shellcheck
# Version management
version:
@grep '^metadata:' SKILL.md | grep -oP '"version":\s*"\K[^"]+'
# Developer setup
install-tools:
@echo "Checking lefthook..."
@command -v lefthook >/dev/null 2>&1 || (echo "Install lefthook: https://github.com/evilmartians/lefthook#install" && exit 1)
@echo "Checking shellcheck..."
@command -v shellcheck >/dev/null 2>&1 || (echo "Install shellcheck: https://github.com/koalaman/shellcheck#installing" && exit 1)
@echo "All tools installed."
hooks:
lefthook install

106
README.md Normal file
View file

@ -0,0 +1,106 @@
# torrentclaw-skill
**Version:** 0.1.13
**License:** MIT
**Homepage:** https://torrentclaw.com
Agent Skill for searching and downloading torrents via [TorrentClaw](https://torrentclaw.com).
Compatible with Claude Code, OpenClaw, Codex CLI, Cline, Roo Code, and any tool supporting the [Agent Skills](https://agentskills.io) specification.
**Alternative:** For Claude Desktop, Cursor, or Windsurf, use the [MCP Server](https://torrentclaw.com/mcp) instead (`npx @torrentclaw/mcp`).
## Features
- Search movies and TV shows across 12+ torrent sources (YTS, EZTV, Knaben, Prowlarr, Bitmagnet, Torrentio, DonTorrent, Torrents.csv, and more)
- Filter by quality (480p-2160p), genre, year, rating, language, season/episode (S01E05, 1x05)
- API key authentication for higher rate limits (120 req/min free, 1K req/min pro)
- Quality scoring (0-100) based on resolution, codec, seeders, source trust
- Multi-language support (11 languages with accent-insensitive search)
- Detect installed torrent clients (Transmission, aria2)
- Add magnet links directly to your torrent client
- Download .torrent files or copy magnet links
- OS-specific installation guides for torrent clients
## Install
### Claude Code
```bash
# Personal (all projects)
ln -s /path/to/torrentclaw-skill ~/.claude/skills/torrentclaw
# Or project-specific
ln -s /path/to/torrentclaw-skill .claude/skills/torrentclaw
```
### OpenClaw
```bash
claw skill install torrentclaw
# or from local
ln -s /path/to/torrentclaw-skill ~/.openclaw/skills/torrentclaw
```
### ClawHub
```bash
clawhub install torrentclaw
```
## Usage
```
/torrentclaw "Inception 1080p"
/torrentclaw "Breaking Bad S05E14"
/torrentclaw "best 4K movies 2024"
```
Or just ask naturally:
> "Find me Inception in the best quality"
> "I need Breaking Bad season 5 episode 14"
> "Search for sci-fi movies from 2023 in 4K"
The skill will:
1. Detect your torrent client (Transmission, aria2)
2. Search TorrentClaw across 12+ sources
3. Present results ranked by quality score (0-100)
4. Add best torrent to your client or provide magnet link
5. Show install guide if no client detected
## Scripts
| Script | Purpose |
|--------|---------|
| `scripts/detect-client.sh` | Detect Transmission/aria2 and output JSON |
| `scripts/add-torrent.sh` | Add magnet to detected client |
| `scripts/install-guide.sh` | Show OS-specific install instructions |
## API
Public API at `https://torrentclaw.com/api/v1/`.
**Authentication:** Optional. Anonymous usage allows 30 req/min. API keys provide higher limits:
- **Free tier**: 120 req/min, 1,000 req/day
- **Pro tier**: 1,000 req/min, 10,000 req/day
See [references/api-reference.md](references/api-reference.md) for full documentation and [SKILL.md](SKILL.md) for workflow examples.
## Links
- **Website**: https://torrentclaw.com
- **Skill Documentation**: https://torrentclaw.com/skill
- **MCP Server**: https://torrentclaw.com/mcp
- **API Reference**: https://torrentclaw.com/api/docs
- **OpenAPI Spec**: https://torrentclaw.com/api/openapi.json
- **Changelog**: [CHANGELOG.md](CHANGELOG.md)
- **GitHub**: https://github.com/torrentclaw/torrentclaw-skill
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
## License
MIT — See [LICENSE](LICENSE) for details.

290
SKILL.md Normal file
View file

@ -0,0 +1,290 @@
---
name: torrentclaw
description: Search and download torrents via TorrentClaw. Use when the user asks to find, search, or download movies, TV shows, or torrents. Detects local torrent clients (Transmission, aria2) and adds magnets directly, or offers magnet link copy and .torrent file download. Supports filtering by type (movie/show), genre, year, quality (480p-2160p), rating, language, and season/episode (S01E05, 1x05). Features API key authentication with tiered rate limits, AI-verified matching, and quality scoring (0-100). Returns titles with posters, ratings, and torrents with magnet links and quality scores.
license: MIT
metadata: {"version": "0.1.13", "repository": "https://github.com/torrentclaw/torrentclaw-skill", "homepage": "https://torrentclaw.com", "openclaw": {"emoji": "🎬", "os": ["darwin", "linux", "win32"]}}
---
# TorrentClaw
Search movies and TV shows across multiple torrent sources with TMDB metadata enrichment. Detect local torrent clients and start downloads automatically.
## Base URL
```
https://torrentclaw.com
```
## Workflow
Follow these steps when the user asks to find or download a torrent:
### Step 1: Detect torrent clients
Run the detection script to check what's available on the user's system:
```bash
bash "$(dirname "$0")/scripts/detect-client.sh"
```
The script outputs JSON with detected clients and OS info. Remember the result for Step 4.
### Step 2: Search for content
Query the TorrentClaw API. Always include the `x-search-source: skill` header for analytics:
```bash
curl -s -H "x-search-source: skill" "https://torrentclaw.com/api/v1/search?q=QUERY&sort=seeders&limit=5"
```
**Useful filters** (append as query params):
- `type=movie` or `type=show`
- `quality=1080p` (also: 720p, 2160p, 480p)
- `genre=Action` (see references/api-reference.md for full list)
- `year_min=2020&year_max=2025`
- `min_rating=7`
- `lang=es` (ISO 639 language code)
- `season=1` — Filter by TV show season
- `episode=5` — Filter by episode number
- `locale=es` — Get titles in Spanish (also: fr, de, pt, it, ja, ko, zh, ru, ar)
- `sort=seeders` (also: relevance, year, rating, added)
### Step 3: Present results
Display results in a clear table format. For each content item show:
- Title, year, content type
- IMDb rating (or TMDB rating as fallback)
- For each torrent: quality, codec, size (human-readable), seeders
Example format:
```
1. Inception (2010) - Movie - IMDb: 8.8
a) 1080p BluRay x265 - 2.1 GB - 847 seeders
b) 2160p WEB-DL x265 HDR - 8.3 GB - 234 seeders
c) 720p BluRay x264 - 1.0 GB - 156 seeders
```
Ask the user which torrent they want.
### Step 4: Handle download
Based on the detection from Step 1:
**If a torrent client was detected:**
Offer to add the magnet link directly:
```bash
bash "$(dirname "$0")/scripts/add-torrent.sh" "MAGNET_URL"
```
Or with a specific client and download directory:
```bash
bash "$(dirname "$0")/scripts/add-torrent.sh" "MAGNET_URL" --client transmission --download-dir ~/Downloads
```
**If NO torrent client was detected:**
Offer these options:
1. **Copy magnet link** — Give the user the full `magnetUrl` from the API response to copy
2. **Download .torrent file**`curl -o "filename.torrent" "https://torrentclaw.com/api/v1/torrent/INFO_HASH"`
3. **Install a client** — Run the install guide script:
```bash
bash "$(dirname "$0")/scripts/install-guide.sh" transmission
```
Recommend **Transmission** for Linux/macOS (lightweight daemon, simple CLI) and **aria2** as alternative (multi-protocol, no daemon needed).
## Endpoints
### Search — `GET /api/v1/search`
Main search endpoint. Required: `q` (query string).
**Filters:** `type` (movie/show), `genre`, `year_min`, `year_max`, `min_rating` (0-10), `quality` (480p/720p/1080p/2160p), `lang` (ISO 639), `availability` (all/available/unavailable).
**Sorting:** `sort` = relevance | seeders | year | rating | added
**Pagination:** `page` (1-1000), `limit` (1-50, default 20)
**Response:** `{ total, page, pageSize, results: [{ id, imdbId, tmdbId, contentType, title, year, overview, posterUrl, genres, ratingImdb, ratingTmdb, hasTorrents, maxSeeders, torrents: [{ infoHash, magnetUrl, torrentUrl, quality, codec, sourceType, sizeBytes, seeders, leechers, source, qualityScore, scrapedAt, languages, audioCodec, hdrType }] }] }`
**New fields:**
- `hasTorrents` (boolean) — Whether content has any associated torrents
- `maxSeeders` (number) — Highest seeder count across all torrents for this content
- `scrapedAt` (string) — ISO timestamp of last tracker scrape for real-time seeder/leecher counts
### Autocomplete — `GET /api/v1/autocomplete`
Fast typeahead. Param: `q` (min 2 chars). Returns max 8 suggestions.
### Popular — `GET /api/v1/popular`
Trending content by seeders. Params: `limit` (1-24), `page`.
### Recent — `GET /api/v1/recent`
Recently added content. Params: `limit` (1-24), `page`.
### Torrent File — `GET /api/v1/torrent/{infoHash}`
Download .torrent file by 40-char hex info hash. Returns binary `application/x-bittorrent`.
### Stats — `GET /api/v1/stats`
Content/torrent counts and recent ingestion history. No params.
### Content Details — `GET /api/v1/content/:id`
Full metadata for a specific movie or show. Returns complete content object with all torrents, cast, crew, and metadata.
### Track — `GET /api/v1/track`
Analytics tracking endpoint. Params: `contentId` (required), `type` (view/click/download).
### Search Analytics — `GET /api/v1/search-analytics`
Popular searches and trending queries. **Requires API key with pro tier.**
### Cache Stats — `GET /api/v1/cache-stats`
Search cache metrics and performance stats. No params.
### Enrichment Stats — `GET /api/v1/enrichment-stats`
TMDB enrichment progress and coverage statistics. No params.
## Season & Episode Search
TorrentClaw supports smart episode filtering with multiple formats:
**Supported formats:**
- `S01E05` (standard format)
- `1x05` (alternative format)
- `1x05-1x08` (episode ranges)
- `Season 1 Episode 5` (natural language)
**Usage:**
1. **In query text** (automatic parsing):
```bash
curl "https://torrentclaw.com/api/v1/search?q=breaking+bad+S05E14"
```
2. **With explicit parameters**:
```bash
curl "https://torrentclaw.com/api/v1/search?q=breaking+bad&season=5&episode=14"
```
The API automatically detects episode patterns in queries and filters results accordingly.
## API Authentication
TorrentClaw supports optional API key authentication for higher rate limits.
**Rate Limit Tiers:**
| Tier | Requests/min | Requests/day | Authentication |
|------|--------------|--------------|----------------|
| Anonymous | 30 | Unlimited | None |
| Free | 120 | 1,000 | API key required |
| Pro | 1,000 | 10,000 | API key required |
| Internal | Unlimited | Unlimited | API key required |
**Using an API key:**
```bash
# Via header (recommended)
curl -H "Authorization: Bearer tc_live_xxxxx" \
"https://torrentclaw.com/api/v1/search?q=dune"
# Via query parameter
curl "https://torrentclaw.com/api/v1/search?q=dune&api_key=tc_live_xxxxx"
```
**Rate limit headers in response:**
- `X-RateLimit-Tier` - Your current tier (anonymous/free/pro/internal)
- `X-RateLimit-Remaining` - Requests remaining in current window
**Getting an API key:**
Contact via https://torrentclaw.com/contact or https://torrentclaw.com/api/v1/contact
## MCP Server Integration
For users of **Claude Desktop**, **Cursor**, or **Windsurf**, TorrentClaw is also available as an MCP (Model Context Protocol) server:
```bash
npx @torrentclaw/mcp
```
**MCP vs Skill:**
- **Skill (this file)**: For OpenClaw, Claude Code, Cline, Roo Code — natural language interface
- **MCP Server**: For Claude Desktop, Cursor, Windsurf — structured tools interface
- **Both** use the same TorrentClaw API backend
See https://torrentclaw.com/mcp for MCP installation and usage.
## Common Patterns
**Find best quality torrent for a movie:**
Search with `sort=seeders`, pick the torrent with highest `qualityScore`.
**Find 4K content:**
Use `quality=2160p` filter.
**Browse Spanish-language torrents:**
Use `lang=es` filter.
**Search for a specific TV episode:**
```bash
curl "https://torrentclaw.com/api/v1/search?q=entrevias+S01E05&locale=es"
```
**Search with API key for higher rate limits:**
```bash
curl -H "Authorization: Bearer tc_live_xxxxx" \
"https://torrentclaw.com/api/v1/search?q=dune&quality=2160p"
```
**Find popular sci-fi movies:**
```bash
curl "https://torrentclaw.com/api/v1/search?genre=science-fiction&type=movie&sort=seeders"
```
**Track content view for analytics:**
```bash
curl "https://torrentclaw.com/api/v1/track?contentId=123&type=view"
```
## Troubleshooting
**Scripts not executable:** Run `chmod +x scripts/*.sh` in the skill directory.
**Transmission not detected but installed:** Ensure `transmission-remote` is in PATH. On some systems the package is `transmission-cli`.
**aria2 starts but exits immediately:** aria2c in direct mode downloads to current directory. Use `--download-dir` flag or `--daemon` mode.
**No torrent client detected:** Run `bash scripts/install-guide.sh transmission` to see installation instructions for your OS (Linux, macOS, Windows/WSL).
**API key not working:**
- Verify the key format: `tc_live_` followed by 32 hex characters
- Check the `Authorization: Bearer <key>` header is correct
- Ensure the key hasn't expired (contact support if needed)
- Check `X-RateLimit-Tier` header in responses to confirm tier
**Rate limits:**
- Anonymous: 30 req/min (no auth)
- Free tier: 120 req/min, 1K/day (with API key)
- Pro tier: 1K req/min, 10K/day (with API key)
- If you get 429, wait a moment or use an API key for higher limits
**Windows users:** Scripts require bash. Use WSL (Windows Subsystem for Linux) or Git Bash.
## Links
- **Website**: https://torrentclaw.com
- **GitHub**: https://github.com/torrentclaw/torrentclaw-skill
- **OpenAPI Spec**: https://torrentclaw.com/api/openapi.json
- **Swagger UI**: https://torrentclaw.com/api/docs
- **MCP Server**: https://torrentclaw.com/mcp
- **llms.txt**: https://torrentclaw.com/llms.txt

29
lefthook.yml Normal file
View file

@ -0,0 +1,29 @@
rc: ./.lefthookrc
commit-msg:
commands:
validate:
run: |
msg=$(head -1 {1})
if ! echo "$msg" | grep -qE '^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?(!)?: .{1,}$'; then
echo ""
echo "ERROR: Invalid commit message format."
echo ""
echo " Got: $msg"
echo ""
echo " Expected: <type>[optional scope][!]: <description>"
echo ""
echo " Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert"
echo " Examples:"
echo " feat: add qBittorrent client detection"
echo " fix(detect): correct aria2 daemon check"
echo " docs: update API reference"
echo ""
exit 1
fi
pre-commit:
commands:
shellcheck:
glob: "*.sh"
run: shellcheck {staged_files}

165
references/api-reference.md Normal file
View file

@ -0,0 +1,165 @@
# TorrentClaw API Reference
## Search Response Schema
```json
{
"total": 42,
"page": 1,
"pageSize": 20,
"results": [
{
"id": 1,
"imdbId": "tt1375666",
"tmdbId": "27205",
"contentType": "movie",
"title": "Inception",
"titleOriginal": "Inception",
"year": 2010,
"overview": "A thief who steals corporate secrets...",
"posterUrl": "https://image.tmdb.org/t/p/w500/oYuLEt3zVCKq57qu2F8dT7NIa6f.jpg",
"genres": ["Action", "Science Fiction", "Adventure"],
"ratingImdb": "8.8",
"ratingTmdb": "8.4",
"contentUrl": "/movies/inception-2010-1",
"hasTorrents": true,
"maxSeeders": 847,
"torrents": [
{
"infoHash": "aaf1e71c0a0e3b1c0f1a2b3c4d5e6f7a8b9c0d1e",
"magnetUrl": "magnet:?xt=urn:btih:aaf1e71c...&dn=Inception+2010+1080p&tr=udp://tracker.opentrackr.org:1337/announce&tr=...",
"torrentUrl": "/api/v1/torrent/aaf1e71c0a0e3b1c0f1a2b3c4d5e6f7a8b9c0d1e",
"quality": "1080p",
"codec": "x265",
"sourceType": "BluRay",
"sizeBytes": "2147483648",
"seeders": 847,
"leechers": 23,
"source": "yts",
"qualityScore": 85,
"scrapedAt": "2026-02-13T10:30:00Z",
"uploadedAt": "2024-03-15T12:00:00Z",
"languages": ["en"],
"audioCodec": "AAC",
"hdrType": null,
"releaseGroup": "YTS",
"season": null,
"episode": null
}
]
}
]
}
```
## Allowed Genres
Action, Adventure, Animation, Comedy, Crime, Documentary, Drama, Family, Fantasy, History, Horror, Music, Mystery, Romance, Science Fiction, Thriller, War, Western, Reality, Talk, News, Soap, Kids, TV Movie, Action & Adventure, Sci-Fi & Fantasy, War & Politics
## API Key Authentication
**Request Headers:**
```
Authorization: Bearer tc_live_xxxxx
```
Or via query parameter:
```
?api_key=tc_live_xxxxx
```
**Response Headers:**
```
X-RateLimit-Tier: free
X-RateLimit-Remaining: 115
X-Api-Key-Id: tc_live_abc1
```
**Rate Limit Tiers:**
- **Anonymous**: 30 req/min (no key)
- **Free**: 120 req/min, 1,000 req/day (with API key)
- **Pro**: 1,000 req/min, 10,000 req/day (with API key)
- **Internal**: Unlimited (with API key)
## New Query Parameters
**Season & Episode Filtering:**
- `season=1` — Filter by TV show season number
- `episode=5` — Filter by episode number
- Note: Also supports parsing from query text (e.g., `q=breaking+bad+S01E05`)
**Localization:**
- `locale=es` — Get titles in Spanish (also: fr, de, pt, it, ja, ko, zh, ru, ar)
## New Response Fields
**Content fields:**
- `hasTorrents` (boolean) — Whether content has associated torrents
- `maxSeeders` (number) — Highest seeder count across all torrents for this content
**Torrent fields:**
- `scrapedAt` (string, ISO 8601) — Timestamp of last tracker scrape for real-time seeder/leecher counts
## Error Responses
| Status | Meaning |
|--------|---------|
| 400 | Invalid parameters (missing q, bad genre, etc.) |
| 404 | Torrent file not found (torrent endpoint only) |
| 429 | Rate limited |
| 500 | Internal server error |
## Rate Limits
| Endpoint | Limit |
|----------|-------|
| /api/v1/search | 30/min |
| /api/v1/autocomplete | 60/min |
| /api/v1/stats | 10/min |
| /api/v1/torrent | 20/min |
## Torrent Download Integration
### Using magnetUrl with Transmission
```bash
# Search and add best torrent to Transmission
RESULT=$(curl -s -H "x-search-source: skill" "https://torrentclaw.com/api/v1/search?q=inception&type=movie&sort=seeders&limit=1")
MAGNET=$(echo "$RESULT" | jq -r '.results[0].torrents[0].magnetUrl')
transmission-remote -a "$MAGNET"
```
### Using magnetUrl with aria2
```bash
RESULT=$(curl -s -H "x-search-source: skill" "https://torrentclaw.com/api/v1/search?q=inception&sort=seeders&limit=1")
MAGNET=$(echo "$RESULT" | jq -r '.results[0].torrents[0].magnetUrl')
aria2c "$MAGNET" --dir=~/Downloads
```
### Downloading .torrent files
```bash
# Get info hash from search result
INFO_HASH=$(echo "$RESULT" | jq -r '.results[0].torrents[0].infoHash')
# Download .torrent file
curl -o "movie.torrent" "https://torrentclaw.com/api/v1/torrent/$INFO_HASH"
# The file includes a descriptive filename in Content-Disposition header:
# TorrentClaw.com-Inception-1080p-EN.torrent
```
## Data Sources
| Source | Content | Notes |
|--------|---------|-------|
| YTS | Movies | High quality, IMDb IDs |
| EZTV | TV Shows | Episode torrents, IMDb IDs |
| Knaben | Mixed | Meta-search aggregator |
| Prowlarr | Mixed | Indexer aggregator |
| Bitmagnet | Mixed | DHT discovery |
| Torrentio | Mixed | Stremio ecosystem |
| DonTorrent | Mixed | Spanish content |
| Torrents.csv | Mixed | Open dataset |
| TMDB | Metadata | Posters, genres, translations |

105
scripts/add-torrent.sh Executable file
View file

@ -0,0 +1,105 @@
#!/usr/bin/env bash
# Adds a magnet link to a detected torrent client.
# Usage: ./add-torrent.sh "<magnet_url>" [--client transmission|aria2] [--download-dir /path]
#
# Exit codes:
# 0 - Success
# 1 - Invalid parameters
# 2 - No torrent client found
# 3 - Client error (failed to add)
set -euo pipefail
# --- Parse Arguments ---
magnet_url=""
client=""
download_dir=""
while [[ $# -gt 0 ]]; do
case "$1" in
--client)
client="$2"
shift 2
;;
--download-dir)
download_dir="$2"
shift 2
;;
-*)
echo "Error: Unknown option $1" >&2
exit 1
;;
*)
if [ -z "$magnet_url" ]; then
magnet_url="$1"
fi
shift
;;
esac
done
if [ -z "$magnet_url" ]; then
echo "Error: Magnet URL is required" >&2
echo "Usage: $0 \"<magnet_url>\" [--client transmission|aria2] [--download-dir /path]" >&2
exit 1
fi
# --- Auto-detect client if not specified ---
if [ -z "$client" ]; then
if command -v transmission-remote >/dev/null 2>&1; then
client="transmission"
elif command -v aria2c >/dev/null 2>&1; then
client="aria2"
else
echo "Error: No torrent client detected. Install transmission-cli or aria2." >&2
exit 2
fi
fi
# --- Add torrent ---
case "$client" in
transmission)
args=(-a "$magnet_url")
if [ -n "$download_dir" ]; then
args+=(-w "$download_dir")
fi
echo "Adding to Transmission..."
if transmission-remote "${args[@]}"; then
echo "Torrent added to Transmission successfully."
else
echo "Error: Failed to add torrent to Transmission. Is the daemon running?" >&2
echo "Start it with: transmission-daemon" >&2
exit 3
fi
;;
aria2)
# Check if aria2 RPC is running
if curl -sf http://localhost:6800/jsonrpc -d '{"jsonrpc":"2.0","id":"test","method":"aria2.getVersion"}' >/dev/null 2>&1; then
echo "Adding to aria2 via RPC..."
dir_param=""
if [ -n "$download_dir" ]; then
dir_param=",{\"dir\":\"$download_dir\"}"
fi
result=$(curl -sf http://localhost:6800/jsonrpc -d "{\"jsonrpc\":\"2.0\",\"id\":\"add\",\"method\":\"aria2.addUri\",\"params\":[[\"$magnet_url\"]$dir_param]}")
if echo "$result" | grep -q '"result"'; then
echo "Torrent added to aria2 successfully."
else
echo "Error: aria2 RPC rejected the request." >&2
exit 3
fi
else
# Direct download mode
echo "Adding to aria2 (direct mode)..."
args=("$magnet_url")
if [ -n "$download_dir" ]; then
args+=(--dir="$download_dir")
fi
aria2c "${args[@]}" &
echo "aria2 download started in background (PID: $!)."
fi
;;
*)
echo "Error: Unknown client '$client'. Supported: transmission, aria2" >&2
exit 1
;;
esac

78
scripts/detect-client.sh Executable file
View file

@ -0,0 +1,78 @@
#!/usr/bin/env bash
# Detects installed torrent clients and outputs JSON.
# Usage: ./detect-client.sh
set -euo pipefail
# --- OS Detection ---
os_name=$(uname -s)
distro="unknown"
case "$os_name" in
Linux)
if [ -f /etc/os-release ]; then
# shellcheck source=/dev/null
distro=$(. /etc/os-release && echo "${ID:-unknown}")
fi
;;
Darwin)
distro="macos"
;;
MINGW*|MSYS*|CYGWIN*)
os_name="Windows"
distro="windows"
;;
esac
# --- Client Detection ---
# Transmission
transmission_path=$(command -v transmission-remote 2>/dev/null || true)
transmission_installed="false"
transmission_daemon="false"
if [ -n "$transmission_path" ]; then
transmission_installed="true"
if transmission-remote -l >/dev/null 2>&1; then
transmission_daemon="true"
fi
fi
# aria2
aria2_path=$(command -v aria2c 2>/dev/null || true)
aria2_installed="false"
aria2_daemon="false"
if [ -n "$aria2_path" ]; then
aria2_installed="true"
if curl -sf http://localhost:6800/jsonrpc -d '{"jsonrpc":"2.0","id":"test","method":"aria2.getVersion"}' >/dev/null 2>&1; then
aria2_daemon="true"
fi
fi
# --- Preferred Client ---
preferred="none"
if [ "$transmission_installed" = "true" ]; then
preferred="transmission"
elif [ "$aria2_installed" = "true" ]; then
preferred="aria2"
fi
# --- JSON Output ---
cat <<EOF
{
"os": "$os_name",
"distro": "$distro",
"clients": {
"transmission": {
"installed": $transmission_installed,
"path": $([ -n "$transmission_path" ] && echo "\"$transmission_path\"" || echo "null"),
"daemonRunning": $transmission_daemon
},
"aria2": {
"installed": $aria2_installed,
"path": $([ -n "$aria2_path" ] && echo "\"$aria2_path\"" || echo "null"),
"daemonRunning": $aria2_daemon
}
},
"preferred": "$preferred"
}
EOF

122
scripts/install-guide.sh Executable file
View file

@ -0,0 +1,122 @@
#!/usr/bin/env bash
# Shows OS-specific installation instructions for torrent clients.
# Usage: ./install-guide.sh [transmission|aria2]
set -euo pipefail
client="${1:-transmission}"
# --- OS Detection ---
os_name=$(uname -s)
distro="unknown"
case "$os_name" in
Linux)
if [ -f /etc/os-release ]; then
# shellcheck source=/dev/null
distro=$(. /etc/os-release && echo "${ID:-unknown}")
fi
;;
Darwin)
distro="macos"
;;
MINGW*|MSYS*|CYGWIN*)
distro="windows"
;;
esac
echo "=== Install $client ==="
echo ""
case "$client" in
transmission)
case "$distro" in
ubuntu|debian|pop|linuxmint|elementary)
echo "Ubuntu/Debian:"
echo " sudo apt update && sudo apt install -y transmission-cli transmission-daemon"
echo ""
echo "Start daemon:"
echo " sudo systemctl start transmission-daemon"
;;
fedora|rhel|centos|rocky|alma)
echo "Fedora/RHEL:"
echo " sudo dnf install -y transmission-cli transmission-daemon"
echo ""
echo "Start daemon:"
echo " sudo systemctl start transmission-daemon"
;;
arch|manjaro|endeavouros)
echo "Arch Linux:"
echo " sudo pacman -S transmission-cli"
echo ""
echo "Start daemon:"
echo " sudo systemctl start transmission"
;;
macos)
echo "macOS:"
echo " brew install transmission-cli"
echo ""
echo "Start daemon:"
echo " transmission-daemon"
;;
windows)
echo "Windows:"
echo " Option 1: Use WSL and install with apt (recommended)"
echo " wsl sudo apt install -y transmission-cli transmission-daemon"
echo ""
echo " Option 2: Download Transmission for Windows"
echo " https://transmissionbt.com/download/"
;;
*)
echo "Install transmission-cli using your distribution's package manager."
echo "Package name is usually: transmission-cli or transmission-daemon"
;;
esac
echo ""
echo "Verify installation:"
echo " transmission-remote --version"
;;
aria2)
case "$distro" in
ubuntu|debian|pop|linuxmint|elementary)
echo "Ubuntu/Debian:"
echo " sudo apt update && sudo apt install -y aria2"
;;
fedora|rhel|centos|rocky|alma)
echo "Fedora/RHEL:"
echo " sudo dnf install -y aria2"
;;
arch|manjaro|endeavouros)
echo "Arch Linux:"
echo " sudo pacman -S aria2"
;;
macos)
echo "macOS:"
echo " brew install aria2"
;;
windows)
echo "Windows:"
echo " Option 1: Use WSL and install with apt (recommended)"
echo " wsl sudo apt install -y aria2"
echo ""
echo " Option 2: Download aria2 for Windows"
echo " https://github.com/aria2/aria2/releases"
;;
*)
echo "Install aria2 using your distribution's package manager."
echo "Package name is usually: aria2"
;;
esac
echo ""
echo "Verify installation:"
echo " aria2c --version"
echo ""
echo "Optional - Start RPC daemon for remote control:"
echo " aria2c --enable-rpc --rpc-listen-port=6800 --daemon"
;;
*)
echo "Unknown client: $client"
echo "Supported clients: transmission, aria2"
exit 1
;;
esac