unarr/CONTRIBUTING.md
Deivid Soto 29cf0a0126 feat: initial commit — unarr CLI
Search, inspect, stream, and download torrents from the terminal.
Replaces the entire *arr stack with a single binary.
2026-03-28 11:29:42 +01:00

6.3 KiB

Contributing to unarr

Thank you for your interest in contributing! This guide will help you get started.

Getting Started

  1. Fork the repository on GitHub
  2. Clone your fork locally:
    git clone https://github.com/YOUR-USERNAME/torrentclaw-cli.git
    cd torrentclaw-cli
    
  3. 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
    
  4. Create a branch for your change:
    git checkout -b feature/my-feature
    
  5. Make your changes, write tests, and ensure everything passes
  6. Commit with a clear message (see Commit Messages)
  7. 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, run go vet, build, and run golangci-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 gofmt on all code (or make fmt)
  • Run golangci-lint (or make 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

  1. Create internal/cmd/mycommand.go
  2. Define a newMyCommandCmd() *cobra.Command function
  3. Add it to rootCmd.AddCommand(...) in root.go
  4. 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!