Search, inspect, stream, and download torrents from the terminal. Replaces the entire *arr stack with a single binary.
6.3 KiB
6.3 KiB
Contributing to unarr
Thank you for your interest in contributing! This guide will help you get started.
Getting Started
- Fork the repository on GitHub
- Clone your fork locally:
git clone https://github.com/YOUR-USERNAME/torrentclaw-cli.git cd torrentclaw-cli - Set up the Go client (local dependency):
# Clone the go-client next to the CLI cd .. git clone https://github.com/torrentclaw/go-client.git cd torrentclaw-cli - Create a branch for your change:
git checkout -b feature/my-feature - Make your changes, write tests, and ensure everything passes
- Commit with a clear message (see Commit Messages)
- Push to your fork and open a Pull Request
Development Setup
You need Go 1.22+ installed.
Build and Run
make build # Build the binary
./unarr --help # Test it
# Or install to GOPATH/bin
make install
Git Hooks (Lefthook)
This project uses Lefthook to run pre-commit checks and validate commit messages automatically.
# Install lefthook (pick one):
brew install lefthook # macOS
go install github.com/evilmartians/lefthook@latest # Go
npm install -g lefthook # npm
# Activate hooks in your local clone:
make install-hooks
# or: lefthook install
Once installed, every commit will automatically:
- pre-commit: check
gofmt, rungo vet, build, and rungolangci-lint(if installed) - commit-msg: validate the message follows Conventional Commits
Make Targets
make build # Build the binary
make test # Run tests
make coverage # Run tests with coverage
make lint # Run golangci-lint
make fmt # Format code (gofmt -s -w)
make check # Verify formatting (no write, CI-friendly)
make vet # Run go vet
make install # Install to GOPATH/bin
make all # fmt + vet + lint + test + build
make install-hooks # Install lefthook git hooks
Project Structure
torrentclaw-cli/
├── cmd/unarr/ # Entry point
│ └── main.go
├── internal/
│ ├── cmd/ # Cobra command definitions
│ │ ├── root.go # Root command + global flags
│ │ ├── search.go # Search command
│ │ ├── inspect.go # Inspect (TrueSpec) command
│ │ ├── watch.go # Watch (streaming + torrents)
│ │ ├── popular.go # Popular/recent content
│ │ ├── config.go # Interactive configuration
│ │ ├── setup.go # First-time setup wizard
│ │ ├── daemon.go # Daemon mode (start/stop)
│ │ ├── download.go # One-shot download
│ │ ├── stream.go # Stream to media player
│ │ ├── doctor.go # Diagnostics
│ │ ├── status.go # Daemon status
│ │ └── stubs.go # Stub commands (future)
│ ├── config/ # Configuration management
│ │ ├── config.go # Config struct + TOML parsing
│ │ └── paths.go # XDG-compliant paths
│ ├── engine/ # Download engine
│ │ ├── manager.go # Download orchestration
│ │ ├── task.go # Task state machine
│ │ ├── torrent.go # BitTorrent downloader
│ │ ├── stream.go # Streaming engine
│ │ ├── organize.go # File organization
│ │ └── ... # Verify, resolve, notify, etc.
│ ├── agent/ # API client + daemon
│ │ ├── client.go # HTTP client
│ │ └── daemon.go # Daemon lifecycle
│ ├── ui/ # Output formatting
│ │ ├── table.go # Table rendering
│ │ └── format.go # Size, rating, time formatting
│ └── parser/ # Torrent parsing
│ └── torrent.go # Magnet URI, hash, name parsing
├── go.mod
├── Makefile
└── README.md
Code Style
- Run
gofmton all code (ormake fmt) - Run
golangci-lint(ormake lint) - Follow existing patterns in the codebase
- Keep commands in separate files under
internal/cmd/ - Keep output formatting in
internal/ui/
Running Tests
# All tests
make test
# Specific test
go test -run TestParse -v ./internal/parser/...
# With coverage report
make coverage
Commit Messages
This project enforces Conventional Commits via a git hook. Format:
<type>[optional scope]: <description>
Allowed types: feat, fix, docs, test, chore, refactor, ci, style, perf, build
Examples:
feat: add search by genre
feat(inspect): add HDR detection
fix(search): handle empty results
docs: update README
test: add parser edge case tests
chore: update CI matrix to Go 1.24
Pull Request Guidelines
- Keep PRs focused — one feature or fix per PR
- Include tests for new functionality
- Update documentation if the public API changes
- Ensure all CI checks pass before requesting review
- Link related issues in the PR description
Adding a New Command
- Create
internal/cmd/mycommand.go - Define a
newMyCommandCmd() *cobra.Commandfunction - Add it to
rootCmd.AddCommand(...)inroot.go - Add any UI rendering helpers to
internal/ui/table.go
Reporting Bugs
Open an issue with:
- Description — what went wrong
- Steps to reproduce — minimal commands to trigger the bug
- Expected behavior — what you expected to happen
- Actual behavior — what actually happened
- Environment — Go version, OS, CLI version (
unarr version)
Code of Conduct
This project follows the Contributor Covenant v2.1.
In short:
- Be respectful — treat everyone with dignity regardless of background or experience level
- Be constructive — focus on what's best for the project and community
- Be collaborative — welcome newcomers, help others learn
- No harassment — unacceptable behavior includes trolling, insults, and unwelcome attention
Thank you for helping make unarr better!