Safely trash instead of rm
first = next


That needlessly pollutes the top-level namespace. Please bury that within def trash. Also, the first() call is odd -- it would be more idiomatic to simply call next() when obtaining first element.

    '''unused_names('f.txt') yields f.txt, f.txt_1, f.txt_2, ...'''


That's a code defect. The comment meant to refer to candidate_names().

You might choose to shift the responsibility, to only yield unused names, but the current code is fine, too.

    yield path.with_name('{path.name}_{i}'.format(**locals()))


Passing in **locals() isn't the most readable way. Please just phrase it as

    yield path.with_name(f'{path.name}_{i}')


Docstring:

Metadata is copied; See Python documentation on shutil.copy2 for details.


Kudos for delegating to official docs rather than copying a sentence from them. But it's probably better to point to move(), which itself points to copy2().

\b


Not sure what you meant by \b.

Maybe you don't need the metavar?

The trash_files can sometimes have long directory paths -- consider using SHA1 to compress the directory down to a short unique string.

if not trash_dir:


I don't understand why the click default wasn't set to os.environ.get('TRASH_DIR', '').

You have three expressions you want to probe here, call them d1, d2, d3. Rather than if / then, consider using or:

trash_dir = d1 or d2 or d3


Consider phrasing this

for trash_file_ in trash_files:


as

for trash_file in map(Path, trash_files):


I like the business of finding trash_dest_candidate relative to $HOME or /, whichever works. This could easily be a list of (more than 2) dirs.

    try:
        shutil.move(trash_file, trash_dest)
    except Exception as e:
        print(str(e))
        sys.exit(2)


Catching all exceptions doesn't seem to help you here -- might be better to not catch anything and live with the stack trace. The str() is superfluous. Consider calling exit() with errno from e, rather than constant 2. It appears to me that Ctrl-C is disabled during cross-filesystem file copies.

Overall, it looks like pretty good code that offers a nice service of "collapsing" filenames while avoiding collisions. Consider appending timestamp + pathname to a log file, and automatically pruning month-old files at end of each run, so trash does not grow without bound.