JTorrent is a Java-based torrent manager built around a Spring Boot backend, jlibtorrent, and two clients:
- a lightweight browser-based live monitor served by the backend
- a standalone terminal UI in the
jtorrent-tuimodule
The server exposes REST endpoints for torrent lifecycle management, file-level prioritization, statistics, storage inspection, and real-time updates over WebSocket/STOMP.
- Add torrents from magnet links
- Upload and manage
.torrentfiles - Start, pause, remove, recheck, and reannounce torrents
- View torrent-level statistics, transfer totals, ETA, and share ratios
- Manage files inside a torrent: skip, resume, prioritize, deprioritize, or reset priorities
- Search and filter torrents by status, name, progress, size, and date
- Monitor disk usage and clean up orphaned files in the downloads directory
- Stream live torrent and statistics updates to connected clients
- Use a full-screen terminal UI for day-to-day operation
.
|-- src/main/java/... Spring Boot torrent server
|-- src/main/resources/ App config + static web monitor
|-- jtorrent-tui/ Standalone terminal UI client
|-- downloads/ Default download directory
|-- build.gradle.kts Root server build
`-- settings.gradle.kts Multi-project Gradle settings
- Java 17
- Spring Boot 4
- Spring Web MVC, Validation, WebSocket, Security, Data JPA
- PostgreSQL for persistence
com.frostwire:jlibtorrentfor torrent session management- Springdoc OpenAPI / Swagger UI
- TamboUI for the terminal client
Before running the project locally, make sure you have:
- Java 17 installed
- PostgreSQL running locally on port
5432 - a database named
torrentdb
Important notes:
- The root build currently includes
jlibtorrent-windows, so the backend is configured for Windows development. spring.jpa.hibernate.ddl-autois set tocreate, which recreates the schema on startup. That is convenient for local development, but it is not production-safe.- Security is currently open for development: all HTTP requests are permitted in
SecurityConfig.
Default server configuration lives in application.yaml:
server:
port: 8080
spring:
datasource:
url: jdbc:postgresql://localhost:5432/torrentdb
username: ${DATABASE_USER:postgres}
password: ${DATABASE_PASSWORD:}
torrent:
downloads-path: ./downloads
max-concurrent-downloads: 5
peer-connection-port-min: 6881
peer-connection-port-max: 6889You can override the database credentials with environment variables:
$env:DATABASE_USER="postgres"
$env:DATABASE_PASSWORD="your-password"From the project root:
.\gradlew.bat bootRunOr on macOS/Linux:
./gradlew bootRunOnce the server starts:
- REST API base URL:
http://localhost:8080/api - WebSocket endpoint:
http://localhost:8080/wsusing SockJS/STOMP - Web monitor:
http://localhost:8080/ - Swagger UI:
http://localhost:8080/swagger-ui/index.html
The terminal UI is packaged as a standalone fat JAR.
Run it from a real terminal. Do not launch it with gradlew run, because the Gradle daemon does not provide a proper TTY for the full-screen interface.
Build it:
.\gradlew.bat :jtorrent-tui:shadowJarRun it:
java -jar jtorrent-tui\build\libs\jtorrent-tui-all.jarTo connect to a different server:
java -jar jtorrent-tui\build\libs\jtorrent-tui-all.jar --server http://your-host:8080Common TUI shortcuts:
aadd a torrentEnteropen detailsppauserresumeddeletecrechecktreannounceoopen operations/health view/filter torrents?open helpqquit
Core endpoints:
POST /api/torrentsadd a torrent from a magnet linkPOST /api/torrents/uploadupload a.torrentfileGET /api/torrentslist torrentsGET /api/torrents/{id}fetch one torrentPOST /api/torrents/{id}/startresume a torrentPOST /api/torrents/{id}/pausepause a torrentPOST /api/torrents/{id}/recheckforce piece verificationPOST /api/torrents/{id}/reannouncereannounce to trackersDELETE /api/torrents/{id}?deleteFiles=true|falseremove a torrentGET /api/torrents/{torrentId}/fileslist files inside a torrentPUT /api/torrents/{torrentId}/files/prioritiesupdate file prioritiesPOST /api/torrents/searchadvanced filtering, sorting, and paginationGET /api/stats/overalloverall torrent statisticsGET /api/files/storagedisk usage for the downloads directoryGET /api/files/orphansscan for orphaned filesDELETE /api/files/orphansclean orphaned filesGET /api/system/healthhealth check
Example: add a torrent via magnet link
curl -X POST http://localhost:8080/api/torrents \
-H "Content-Type: application/json" \
-d '{
"magnetLink": "magnet:?xt=urn:btih:YOUR_INFO_HASH",
"savePath": "./downloads",
"startImmediately": true
}'Example: search torrents
curl -X POST http://localhost:8080/api/torrents/search \
-H "Content-Type: application/json" \
-d '{
"statuses": ["DOWNLOADING", "SEEDING"],
"name": "ubuntu",
"sortBy": "addedDate",
"sortDirection": "DESC",
"page": 0,
"size": 20
}'The server publishes WebSocket updates on a schedule:
/topic/torrentsfull torrent list updates/topic/torrents/{id}focused updates for a specific torrent/topic/statsaggregated statistics/topic/notificationsadd/remove/completion notifications
The bundled web page at index.html is a simple monitor that subscribes to those topics and renders live status information in the browser.
Run the test suite from the project root:
.\gradlew.bat testTests use H2 in PostgreSQL compatibility mode via application-test.yaml.
- The backend manages a
SessionManagerfromjlibtorrentand keeps active handles in memory. - The default downloads directory is
downloads. - The TUI talks to the backend over HTTP and also uses live updates for a more responsive experience.
- There are crash logs (
hs_err_pid*.log) and sample downloaded content in the repo right now; you may want to decide later whether those should remain versioned or be ignored.
This repository already has good automated test coverage for controllers, services, repositories, DTOs, mapper logic, and exception handling. On this machine, .\gradlew.bat test completed successfully on March 31, 2026.