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

@hahnfeld/devtunnel-provider

v1.0.3

Published

Microsoft Dev Tunnels provider plugin for OpenACP

Readme

@hahnfeld/devtunnel-provider

Microsoft Dev Tunnels provider plugin for OpenACP — expose local ports to the internet via the devtunnel CLI.

Features

  • Dev Tunnels integration — Uses Microsoft's devtunnel host CLI to create tunnels
  • Auto-start — Automatically starts the tunnel when the OpenACP API server is ready
  • URL change detection — Monitors for URL changes after reconnects and emits events so other plugins automatically pick up the new URL
  • Interactive install wizard — Validates CLI installation and authentication during setup
  • Anonymous access — Configurable --allow-anonymous flag (default: on) for webhook endpoints and viewer links
  • Configurable — Protocol, expiration, cluster region, and port options
  • Security hardened — No shell interpolation, strict input validation, bounded buffers

Prerequisites

  • OpenACP CLI >= 2026.0.0
  • Node.js 18+
  • Microsoft Dev Tunnels CLI (devtunnel)
  • A Microsoft or GitHub account (for devtunnel user login)

Installation

Option A: OpenACP plugin install (recommended)

openacp plugin install @hahnfeld/devtunnel-provider

This launches an interactive wizard that validates your CLI installation and authentication.

Option B: Manual npm install

npm install @hahnfeld/devtunnel-provider
# or
pnpm add @hahnfeld/devtunnel-provider

Dev Tunnels CLI Setup

Before configuring the plugin you need the devtunnel CLI installed and authenticated.

  1. Install the CLI:

    # macOS
    brew install --cask devtunnel
    
    # Linux
    curl -sL https://aka.ms/DevTunnelCliInstall | bash
    
    # Windows
    winget install Microsoft.devtunnel
  2. Log in (required — anonymous hosting is not supported by the CLI):

    devtunnel user login

    Or with GitHub:

    devtunnel user login -g

    Or with device code (when interactive browser login isn't possible):

    devtunnel user login -d

For full details see the Dev Tunnels CLI reference.

Configuration

Interactive wizard

If you installed via openacp plugin install, the wizard runs automatically. To re-configure:

openacp plugin configure @hahnfeld/devtunnel-provider

The wizard guides you through:

  1. CLI presence and authentication validation
  2. Port selection (specific port or auto-detect from API server)
  3. Anonymous access toggle
  4. Protocol selection (auto, HTTP, HTTPS)
  5. Optional tunnel expiration

Manual configuration

Add the following to your plugin settings:

plugins:
  devtunnel-provider:
    enabled: true
    port: null                 # null = auto-detect from API server, or specify e.g. 3100
    allowAnonymous: true       # Required for webhooks/viewer links
    protocol: auto             # auto | http | https
    expiration: null           # e.g., '4h', '2d', or null for session-lived
    cluster: null              # e.g., 'usw2', or null for auto-select

Configuration reference

| Field | Type | Default | Description | |-------|------|---------|-------------| | enabled | boolean | true | Enable the provider | | port | number \| null | null | Local port to tunnel. Null = auto-detect from API server | | allowAnonymous | boolean | true | Allow unauthenticated access to tunnel URLs | | protocol | string | "auto" | Port protocol: auto, http, or https | | expiration | string \| null | null | Tunnel lifetime (e.g., 4h, 2d, max 30d). Null = deleted on exit | | cluster | string \| null | null | Preferred Azure region cluster (e.g., usw2) |

How It Works

  1. On startup, the plugin waits for the api-server:started event
  2. It spawns devtunnel host -p <port> --allow-anonymous as a child process
  3. It parses the public URL from the CLI output (https://<id>-<port>.<cluster>.devtunnels.ms/)
  4. The URL is available via getPublicUrl() and the tunnel-provider:devtunnel service
  5. If the tunnel reconnects with a new URL, the plugin emits a devtunnel-provider:url-changed event

URL Change Detection

When a devtunnel host process reconnects after a network disruption, it may receive a new public URL. This plugin continuously monitors the tunnel output and:

  1. Detects the new URL via line-buffered stdout/stderr parsing
  2. Updates its internal state
  3. Emits a devtunnel-provider:url-changed event with { oldUrl, newUrl }

Other plugins can subscribe to this event to update their webhook registrations, bot endpoints, etc.

Events

| Event | Payload | Description | |-------|---------|-------------| | devtunnel-provider:url-changed | { oldUrl, newUrl } | Tunnel URL changed after reconnect | | devtunnel-provider:started | { publicUrl, port } | Tunnel started successfully |

Known Limitations

No TunnelService.addTunnel() integration

This plugin operates independently of OpenACP's built-in TunnelService. It registers itself as a standalone service (tunnel-provider:devtunnel) and manages its own lifecycle rather than integrating with the central tunnel registry.

This means:

  • addTunnel / listTunnels / stopTunnel commands in the core tunnel system do not see Dev Tunnel instances
  • The plugin cannot be selected as a provider via the tunnel.provider config option
  • Tunnel retry, keepalive, and persistence are handled by the plugin itself, not by TunnelRegistry

Why: OpenACP's TunnelRegistry.createProvider() uses a closed factory — external providers cannot be registered into it. Adding support for plugin-provided tunnel providers would require a change to OpenACP core (e.g., a provider registration hook or a lookup into plugin services).

Planned: We'd like to contribute an extensible provider mechanism to OpenACP so that this plugin (and other third-party providers) can participate in the standard TunnelService lifecycle.

Security

This plugin is designed with security as a priority:

  • No shell interpolation — All subprocess spawning uses spawn() with argv arrays, never shell: true or string interpolation
  • Strict input validation — Port, protocol, expiration, and cluster values are validated against strict patterns before being passed as CLI arguments
  • Binary path validation — Binary paths from which/where are verified to be absolute paths
  • Bounded buffers — Line buffers are capped at 1 MiB to prevent memory exhaustion from runaway subprocess output
  • No credential exposure — Dev Tunnels uses the system keychain for authentication; no secrets are passed via CLI args or environment variables
  • Anonymous access warning — When allowAnonymous is enabled, a conspicuous warning is logged at startup

Anonymous Access Warning

When allowAnonymous: true (the default), the tunnel URL is publicly accessible without authentication. This is required for OpenACP webhook endpoints and viewer links, but means anyone with the URL can access your local service. If your service is not intended to be public, set allowAnonymous: false.

Slash Commands

| Command | Description | |---------|-------------| | /devtunnel | Show current tunnel status | | /devtunnel auth | Check devtunnel CLI authentication |

Uninstalling

openacp plugin uninstall @hahnfeld/devtunnel-provider --purge

The --purge flag removes all saved settings. After uninstalling, you may also want to:

  1. devtunnel delete-all — Remove any persistent tunnels
  2. devtunnel user logout — Clear credentials
  3. brew uninstall --cask devtunnel — Remove the CLI (macOS)

Development

# Install dependencies
pnpm install

# Build
pnpm build

# Watch mode
pnpm dev

# Run tests
pnpm test

Architecture

src/
├── index.ts             # Plugin entry point & public exports
├── plugin.ts            # Plugin factory (install wizard, configure, setup/teardown)
├── provider.ts          # DevTunnelProvider (subprocess management, URL change detection)
├── types.ts             # DevTunnelConfig interface
└── __tests__/
    ├── provider.test.ts # Provider unit tests (URL parsing, change detection, security)
    └── plugin.test.ts   # Plugin shape conformance tests

Tech Stack

License

MIT