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

tailminal

v0.2.2

Published

Use the terminal of any device in your Tailscale tailnet from any other device. Persistent PTY sessions, agent-friendly CLI, web UI on every node.

Downloads

506

Readme

⚡ Tailminal

npm version npm downloads license

Use the terminal of any device in your Tailscale tailnet from any other device — manually via a web UI, interactively via CLI, or programmatically from agents (plain stdin/stdout subprocess).

┌─────────────┐   HTTP + WebSocket    ┌─────────────┐
│  PC (client)│◄─────────────────────►│ Laptop      │
│  tailminal  │    over tailnet       │ (server)    │
└─────────────┘                       └─────────────┘
Every node runs the same single binary: server + CLI + web UI.
No central hub. Discovery via MagicDNS.

Features

  • One-shot exec — run a command on any node, stream stdout/stderr, get the exit code
  • Persistent PTY sessions — interactive shells that survive disconnects; reattach with scrollback replay
  • Agent-friendly CLItailminal exec / tailminal attach are plain stdin/stdout subprocesses any agent framework can spawn
  • Web UI on every node — host list, live xterm.js terminal, one-shot command form
  • Cross-platform — Windows (PowerShell/CMD), macOS (zsh), Linux (bash/sh)
  • Zero-setup tailnet access — Tailscale and loopback clients connect without another credential
  • Automatic discovery — online tailnet devices appear without editing a peer list, with Tailminal availability shown separately

Install

npm install -g tailminal

Or from source:

git clone https://github.com/TheReal-Flo/tailminal
cd tailminal && pnpm install && pnpm build

Start the node server (generates ~/.tailminal/config.json on first run):

tailminal serve        # listens on 0.0.0.0:7601

Configuration — ~/.tailminal/config.json

{
  "port": 7601,
  "auth": "tailnet",
  "discoverPeers": true,
  "sessionTTL": "persistent",
  "peers": [
    { "name": "laptop", "address": "laptop.your-tailnet.ts.net" }
  ]
}

| Key | Default | Meaning | | ------------ | ------------- | -------------------------------------------------------------- | | port | 7601 | Fixed listen port for all nodes | | auth | tailnet | Passwordless access from loopback/Tailscale addresses; use token for legacy bearer auth | | discoverPeers | true | Discover online Tailnet devices and check Tailminal availability | | sessionTTL | persistent | Sessions live until reboot; or auto-reap detached ones (30m, 12h, 7d, …) | | shell | platform default | Override the PTY login shell executable | | peers | [] | MagicDNS hostnames shown in the host list |

With the defaults, no peer list or token setup is needed. Tailminal reads the local tailscale status, adds online peers automatically, and indicates whether Tailminal is running on port 7601. Configured peers remain useful for aliases or devices that cannot be discovered. Requests from LAN and public addresses are rejected even though the server listens on all interfaces. To opt into the old credential flow, set "auth": "token"; the server then creates ~/.tailminal/token, and clients can use that file or TAILMINAL_TOKEN.

CLI

tailminal serve                          Start the node server
tailminal hosts                          List configured peers + status
tailminal exec <host> [opts] -- <cmd...> One-shot command (streams output, propagates exit code)
    --cwd <dir>                          Remote working directory
    --shell <auto|powershell|cmd|sh>     Shell preference (Windows: powershell/cmd)
    --timeout-ms <n>                     Kill after n ms
tailminal attach <host> [session-id]     Interactive PTY over stdio (Ctrl+] detaches, session stays alive)
tailminal sessions <host>                List remote sessions
tailminal token                          Print the token when using auth: "token"

Hosts can be MagicDNS names (laptop), full URLs (http://laptop:7601), or peer names from your config.

Agent usage

Agents need zero integration — just spawn a subprocess:

tailminal exec laptop -- adb devices          # exit code propagates
tailminal attach laptop                        # raw bidirectional shell on stdin/stdout

Web UI

Open http://<node>:7601 over Tailscale, pick a host, and get a live terminal. No credential prompt appears in the default tailnet mode. Device names can be renamed with the edit button; aliases are stored only in that browser and do not change Tailscale or Tailminal configuration.

Autostart

Windows (Task Scheduler, run at logon):

schtasks /create /tn Tailminal /tr "node C:\path\to\apps\cli\dist\index.js serve" /sc onlogon

Linux (systemd user service, ~/.config/systemd/user/tailminal.service):

[Unit]
Description=Tailminal node server

[Service]
ExecStart=/usr/bin/node /opt/tailminal/apps/cli/dist/index.js serve
Restart=on-failure

[Install]
WantedBy=default.target

macOS (launchd, ~/Library/LaunchAgents/dev.tailminal.plist): use RunAtLoad with the same node command.

Monorepo layout

| Package | Purpose | | --------------------- | ------------------------------------------------ | | packages/shared | Zod protocol types shared by all packages | | packages/server | Fastify server, PTY manager, auth, static web UI | | packages/client | HTTP + WebSocket client library | | packages/web (ui-src in server) | xterm.js UI bundled to static/ | | apps/cli | tailminal binary | | website/ | Static marketing site + /llms.txt agent docs |

Development

pnpm build        # build all packages (topological)
pnpm typecheck    # strict tsc across the workspace
pnpm test         # vitest unit tests

Website

website/ is a dependency-free static site. The human-facing page is index.html; agents are pointed at /llms.txt (via an HTML comment, <link rel="llms-txt">, and a footer note) which contains machine-readable setup and API documentation. Serve the folder with any static file server, or point the node server at it:

TAILMINAL_STATIC=./website tailminal serve