npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tailtoss

v0.4.1

Published

A terminal UI for Tailscale's Taildrop — send and receive files over your tailnet with the tailscale CLI.

Readme

English · 한국어

Tailtoss

A clean terminal UI (TUI) for Tailscale's Taildrop. Built for people who send/receive files with the open-source tailscale CLI instead of a GUI client. Pick files, choose a target device, and receive — all from the keyboard.

Send/receive files over your tailnet from the terminal — file browser, device picker. Command: tailtoss.

 🚀 Tailtoss  tailscale file transfer  › Menu
──────────────────────────────────────────────
What would you like to do?
Receive folder: /Users/you/Downloads

❯ 📤  Send files
  📥  Receive files
  ⚙️  Settings
  ❔  Help
  🚪  Quit
──────────────────────────────────────────────
↑↓ move · Enter select · Ctrl+C quit

Why Tailtoss

Taildrop is Tailscale's built-in way to move files between your own devices — no cloud, no accounts. Tailtoss exists to make it easy to actually use: a keyboard-driven terminal UI over the tailscale CLI, so you don't have to memorize tailscale file cp flags or dig up device names. Setup stays light — Node plus the tailscale CLI you already run, nothing more.

On top of the basics, it adds things neither the official CLI nor the GUI offers:

  • Folder sending — folders are zipped automatically before transfer (the CLI sends only files)
  • Free-form multi-select — pick any mix of files and folders in one pass
  • Pre-send name checks — names the receiver would reject (leading/trailing spaces, over-long names, forbidden characters) are caught before sending, telling you which file and why, instead of the bare "transfer failed" the official tools give you

Features

  • Send files — pick from the built-in file browser → choose an online device → transfer
    • Single file → sent as-is
    • Multiple files → send each separately or bundle into one zip (chosen in settings)
    • Folder → always compressed to .zip before sending
    • Target list is auto-populated via tailscale file cp --targets (online, receivable devices only)
  • Receive files — save files from the staging inbox into your downloads folder
    • macOS (Homebrew tailscaled): usually saved as your user with no sudo or auth needed — but if a permission error occurs, follow the sudo command shown on screen
    • Linux and other permission-restricted setups: the required sudo command is shown on screen
    • Name collisions are auto-numbered via --conflict=rename
  • Settings — downloads folder · language · multi-file transfer mode (all persisted for next run)
  • Help — usage instructions available right on screen

Supported platforms

| Platform | Status | Notes | | ----------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | macOS | ✅ Fully supported | Receiving usually needs no sudo (Homebrew tailscaled); if a permission error occurs, the sudo command is shown | | Linux | ✅ Supported | Receiving may need sudo to access the root-owned inbox (command is shown) | | Windows | ⚠️ Experimental | Paths/commands are handled, but testing focuses on macOS & Linux. Folder/bundle sends rely on the built-in tar.exe (Windows 10 1803+); this path is untested on real hardware |

Requirements

This tool targets the open-source tailscale / tailscaled (CLI + daemon). It drives whatever tailscale binary is on your PATH, and the primary audience runs tailscaled themselves — the Homebrew build on macOS (brew install tailscale), or a native Linux install. The tailscale CLI bundled with the official macOS GUI client has also been confirmed to work here; that path is not guaranteed, and other platforms and distributions are untested. tailscaled users are the intended target.

  • Node.js 18+

  • tailscale CLI (open-source build, with tailscaled running) — if missing, the app shows install guidance and exits

  • An archiver — only needed for folder transfers / bundling multiple files into a zip. Sending a single file never needs one. Either of these works, and the app picks whichever it finds:

    • zip (Info-ZIP) — bundled with macOS; on Linux sudo apt install zip, etc.
    • bsdtar — libarchive's tar, which writes .zip directly. Bundled with macOS, and with Windows 10 1803+ / 11 as tar.exe. Note that GNU tar cannot write zip, so a Linux box with only GNU tar still needs zip.

    If neither is found the app warns on the menu (it does not block) and Settings › Check for archiver re-detects after you install one — no restart needed.

npm package dependencies (ink, react, execa, etc.) are handled by npm install. The required runtime tool (tailscale) is checked automatically at startup.

Installation

Install from npm:

npm install -g tailtoss

Then run it from any directory:

tailtoss

To update later, run npm install -g tailtoss@latest.

From source (for development)

git clone https://github.com/dooee/tailtoss.git
cd tailtoss
npm install          # install dependencies
npm run build        # compile to dist/
npm install -g .     # register the global `tailtoss` command

npm link works too and gives you the exact same global tailtoss — only the linking differs: npm install -g . installs a copied snapshot of the build, while npm link symlinks this working directory. So if you plan to edit the source, prefer npm link: after npm run build your changes show up in tailtoss with no reinstall.

Usage

Run tailtoss → move through the menu with the arrow keys, select with Enter.

📤 Send files

File browser controls:

| Key | Action | | ------- | ------------------------------------------------------------------------ | | ↑ ↓ | Move between items | | → | Enter folder | | ← | Parent folder | | Space | Select / deselect (multiple allowed) | | Enter | Start transfer (if nothing is selected, sends the item under the cursor) | | . | Toggle hidden files | | Esc | Cancel |

Transfer rules:

  • Single file → sent as-is
  • Multiple files → send each separately or bundle into one zip, per settings
  • Folder → always compressed to zip before sending

Then pick the target device from the list and it's sent.

📥 Receive files

Choosing Receive files pulls files from the inbox into your downloads folder.

In a headless tailscaled setup, incoming files do not pop up automatically like the GUI app. Run Receive when you want them. If a permission error occurs (Linux, or occasionally macOS depending on your setup), the required sudo command is shown on screen.

⚙️ Settings

  • Change downloads folder — navigate the folder browser, then Enter to select that folder
  • Language — English / Korean
  • Multi-file transfer mode — send each separately / bundle into one zip

Settings are saved to the paths below and persist across runs.

| Platform | Config file | | -------- | --------------------------------------------------------------------- | | macOS | ~/Library/Application Support/tailtoss/config.json | | Linux | $XDG_CONFIG_HOME/tailtoss/config.json (default ~/.config/...) | | Windows | %APPDATA%\tailtoss\config.json |

Development

npm run dev      # run the source directly with tsx
npm run build    # compile to dist/ + set executable bit
npm run start    # run the build output

Project structure

src/
├── cli.tsx            # entry point (shebang) · renders after checking the tailscale dependency
├── app.tsx            # screen routing + language context
├── config.ts          # settings load/save (per-platform paths)
├── i18n.ts            # UI strings · help · context
├── tailscale.ts       # listTargets / sendPaths / receive · CLI detection
├── zip.ts             # zip compression (Info-ZIP or bsdtar) for folders / multiple items
└── components/
    ├── Frame.tsx          # shared frame (title bar + horizontal rule + help)
    ├── MainMenu.tsx
    ├── FileBrowser.tsx    # arrow-key navigation + multi-select (files/folder modes)
    ├── TargetPicker.tsx   # pick a target from the --targets list
    ├── Send.tsx · Receive.tsx · Settings.tsx · Help.tsx

Troubleshooting

  • tailscale CLI not found — install tailscale and confirm tailscale status works. It's auto-detected from /opt/homebrew/bin, /usr/local/bin, /usr/bin, and PATH.
  • Receive fails on Linux (permissions) — run the sudo tailscale file get ... command shown on screen.
  • No archiver found on folder/bundle transfers — install zip (or use a system with
    bsdtar), then re-detect via Settings › Check for archiver. Sending a single file
    works without any archiver.
  • When using nvm — the global install lives in the current Node version's bin, so after nvm use re-run npm link (or npm install -g .) on that version.

Notes

Tailscale is an open-source, WireGuard-based mesh VPN that links your devices into a private network (a tailnet). Taildrop is its built-in device-to-device file transfer feature.

Tailtoss is an independent, unofficial front-end — not affiliated with or endorsed by Tailscale Inc. It isn't a full CLI wrapper: it drives only the Taildrop file-transfer commands (tailscale file cp / file get) behind a TUI, leaving the rest of the CLI alone. It shells out to a tailscale binary you install yourself, so without it the app cannot run — and it says so at startup.

License

MIT