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

@spencerwmiles/woof

v0.0.10

Published

A simple CLI which provides both a server and a client for exposing services to the public internet.

Readme

Woof

                                                                           
                                                                           
                                                                           
                     ████                                                  
                 ███████████                                               
              █████   ███████  ██████████       ██████                     
           ██████   ███████ ███████████████████████████████                
           ██    █ ███████                 ███ ██         ██               
            ██    ██████                 ██   █████  ██  ███               
            ███  ██████             ██      █   ███  █   ██                
            ███████ ██              █  █        ███     ███                
             ██████ █          █    █        ██ ████   ███                 
                  ███                        █   █████████                 
                   ██  █████            ████       ██████                  
                   ███████ ██          ███ ██        ███                   
                   ██  █████           ██████         ██                   
                    ██   █             █████          ██                   
                     ██                              ████                  
                      █      ████                    ██████                
                      ███  ███ ████                 ██  ██████             
                       ██  ████████               ███   ██████████         
                       ██   ██████               ██   ██████████████       
                       ██    ███         █    ███    ████████  █████       
                        ███████ ████   █     ██   ██████   █   █████       
                           █████████      ██    ██████     █████████       
                           ███              ████████    ███████████        
                           ██               █████     ████████████         
                                                                           
                                                                           
                                                                                                                        

A simple CLI which provides both a server and a client for exposing services to the public internet.

Features

  • Secure VPN Connection: Standard WireGuard VPN setup for secure access to remote resources
  • Standard Port Forwarding: Access services running on the VPN server from local clients
  • Reverse Port Forwarding: Expose local development services through a server to the public internet
  • Simple Setup: Easy-to-follow installation and configuration process for both server and client
  • Cross-platform Support: Works on Linux (for production/server) and macOS/Windows (for development/testing)

Architecture

┌────────────────┐            ┌───────────────┐            ┌──────────────────┐
│                │            │               │            │                  │
│  Public Users  │───────────▶│     Server    │◀───────────│  Local Developer │
│                │            │  (WireGuard)  │            │   (WireGuard)    │
└────────────────┘            └───────────────┘            └──────────────────┘
        │                             ▲                             ▲
        │                             │                             │
        │                             │                             │
        └─────────────────────────────┘                             │
        HTTP/HTTPS traffic             ◀─────────────────────────────┘
        (Reverse Forwarded)                     VPN tunnel

Project Structure

.
├── src/                # All source code (CLI and server)
│   └── ...             # (subfolders for server, api, config, etc.)
├── dist/               # Compiled output (after build)
├── package.json        # Project manifest and scripts
├── tsconfig.json       # TypeScript configuration
├── README.md           # This file
└── ...                 # Other config files

Requirements

  • WireGuard: You must have WireGuard installed on both the server and client machines.
    • On Linux: sudo apt install wireguard (Debian/Ubuntu) or sudo yum install wireguard-tools (CentOS/Fedora)
    • On macOS: brew install wireguard-tools
    • On Windows: Download from wireguard.com
  • Server: Linux-based system
  • Client: macOS, Windows, or Linux machine
  • Networking: UDP port 51820 must be open on the server
  • Permissions: Root/sudo access on both server and client
  • Node.js: v16 or higher
  • pnpm: v8 or higher

Setup & Installation

1. Install the CLI

You can install the CLI globally from npm:

pnpm add -g @spencerwmiles/woof
# or
npm install -g @spencerwmiles/woof

This will make the woof command available globally.

2. Ensure WireGuard is Installed

WireGuard is required for all VPN and tunnel operations.
Check if it's installed:

wg --version

If you see a version number, you're good! If not, install it using the instructions above.

3. (Optional) Install pnpm

If you want to develop or run from source, install pnpm:

npm install -g pnpm

Usage

Server Setup

Start the server using the CLI:

woof server start

The CLI will prompt for configuration and start the API server.

Note on API Accessibility: By default, the API server listens on 0.0.0.0 (all network interfaces), making it publicly accessible. To restrict access, set the API_BIND_ADDR environment variable before starting the server:

  • Restrict to localhost: export API_BIND_ADDR=127.0.0.1
  • Restrict to WireGuard interface: export API_BIND_ADDR=10.8.0.1 (or your server's WireGuard IP)

Then run woof server start.

Client Usage

Create a tunnel to expose a local port:

woof up 3000

Use a custom subdomain:

woof up 3000 --subdomain myapp

API Security

The Woof API is secured using API key authentication.

Authentication

All API requests must include a valid API key in the X-API-Key header. Requests without a valid API key will be rejected with a 401 Unauthorized response.

Example:

curl -X GET http://localhost:3000/api/v1/clients \
  -H "X-API-Key: your-api-key-here"

API Key Management

Initial Setup

When the server is first started, an initial API key is automatically generated and displayed in the console. This key will only be shown once, so make sure to save it securely.

Example console output:

=================================================
IMPORTANT: API Key Generated
=================================================
API Key: 3a7c4be1f8d9e2b5a0c6...
This key will not be shown again. Store it securely.
=================================================

Managing API Keys via CLI

Woof provides CLI commands to manage API keys:

Create a New API Key (replaces any existing API key):

woof api-key create

You can optionally provide a name for the key:

woof api-key create --name "My Custom Key"

Revoke All API Keys:

woof api-key revoke

Note: After revoking all keys, API access will be unavailable until a new key is created.

Configuring API Key for Clients

Before using any client commands that communicate with the server (like woof up), you need to configure your client with the API key:

woof config --api-key YOUR_API_KEY_HERE

You can verify your configuration (the key will be shown as masked):

woof config

Security Model

Woof uses a simple security model:

  • Only one API key can be active at a time
  • Creating a new key automatically revokes all previous keys
  • All API endpoints require authentication
  • There are no permission levels - if you have the key, you have full access

Data Storage & Resetting State

Where is state stored?

  • Client: All client configuration, WireGuard config, and tunnel state are stored in ~/.woof in your home directory.
  • Server: All server configuration, database, and WireGuard config are stored in ~/.woof/server in the server's home directory. The server manages its own WireGuard config in ~/.woof/server/wireguard (not /etc/wireguard).

Resetting/Clearing State

  • Client: To fully clear all client state and bring down any running WireGuard interface, run:

    woof reset

    This will bring down the WireGuard interface (if running) and delete all files in ~/.woof.

  • Server: To fully clear all server state, remove all server config, database, and WireGuard config, and clean up any Nginx configs created by Woof, run:

    woof server reset

    or

    woof server clear

    This will delete ~/.woof/server, remove any Nginx configs created by Woof from /etc/nginx/sites-enabled, and reload Nginx.


Development

  1. Clone the repository:

    git clone https://github.com/spencerwmiles/woof.git
    cd woof
  2. Install dependencies:

    pnpm install
  3. Build the project:

    pnpm build
  4. Run the CLI from source:

    pnpm start -- up 3000

License

MIT