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

claude-code-tailscale

v0.2.0

Published

Claude Code plugin that joins a Tailscale tailnet as an ephemeral device using libtailscale

Readme

Claude Code Tailscale Plugin

A Claude Code MCP server that joins a Tailscale tailnet as an ephemeral device, giving Claude access to internal services, APIs, and resources on your tailnet.

How It Works

Claude Code
  └── MCP Server (TypeScript)
        └── tshelper (Go binary using tsnet)
              └── SOCKS5 proxy on localhost
                    └── routes through your tailnet

On first tool invocation, the MCP server spawns tshelper, which:

  1. Joins your tailnet as an ephemeral device using tsnet
  2. Starts a SOCKS5 proxy, a control API, and an agent listener
  3. Returns connection details to the MCP server

Claude can then use tailscale_fetch to access any service on your tailnet — internal APIs, dashboards, databases — without exposing them to the internet. Multiple Claude Code sessions on different machines can discover each other, exchange messages, and coordinate work through shared task lists.

When the session ends, the device explicitly logs out and is immediately removed from your tailnet.

Prerequisites

Setup

1. Configure Credentials

Set your Tailscale credentials (pick one):

# Option A: Auth key (simplest)
export TS_AUTHKEY="tskey-auth-..."

# Option B: OAuth client secret (preferred for automation/CI)
export TS_CLIENT_SECRET="tskey-client-..."
export TS_TAGS="tag:claude-code"  # required for OAuth

2. Add to Claude Code

The simplest way — install directly from npm:

claude mcp add tailscale -- npx -y claude-code-tailscale

Or add to your project's .mcp.json:

{
  "mcpServers": {
    "tailscale": {
      "command": "npx",
      "args": ["-y", "claude-code-tailscale"],
      "env": {
        "TS_AUTHKEY": "tskey-auth-..."
      }
    }
  }
}

With an OAuth client secret:

{
  "mcpServers": {
    "tailscale": {
      "command": "npx",
      "args": ["-y", "claude-code-tailscale"],
      "env": {
        "TS_CLIENT_SECRET": "tskey-client-...",
        "TS_TAGS": "tag:claude-code"
      }
    }
  }
}

With team coordination enabled:

{
  "mcpServers": {
    "tailscale": {
      "command": "npx",
      "args": ["-y", "claude-code-tailscale"],
      "env": {
        "TS_AUTHKEY": "tskey-auth-...",
        "TS_ENABLE_TEAMS": "1"
      }
    }
  }
}

Building from Source

If you prefer to build locally instead of using the npm package:

git clone https://github.com/rosskukulinski/claude-code-tailscale.git
cd claude-code-tailscale

# Build the Go helper
cd tshelper && go build -o ../bin/tshelper . && cd ..

# Install npm dependencies and build TypeScript
npm install && npm run build

# Add to Claude Code
claude mcp add tailscale -- node /path/to/claude-code-tailscale/dist/index.js

Tools

Networking

| Tool | Description | |------|-------------| | tailscale_status | Show tailnet connection status, IPs, and hostname | | tailscale_fetch | HTTP fetch through the tailnet (GET, POST, PUT, DELETE, PATCH, HEAD) | | tailscale_connect_test | Test TCP connectivity to a tailnet host:port | | tailscale_port_forward | Create, list, or close TCP port forwards to tailnet hosts |

Diagnostics

| Tool | Description | |------|-------------| | tailscale_dns_lookup | Resolve DNS names via MagicDNS | | tailscale_whois | Look up info about a tailnet IP (owner, hostname, tags) | | tailscale_devices | List all devices on the tailnet | | tailscale_ping | Ping a tailnet peer (disco, TSMP, ICMP, peerapi) | | tailscale_acl_check | Show ACL packet filter rules for this node | | tailscale_netcheck | DERP relay regions and latency probes | | tailscale_cert | Get TLS certificate info for a tailnet domain |

Inter-Agent Messaging

| Tool | Description | |------|-------------| | tailscale_agents | Discover other Claude Code agents (cc-* peers) on the tailnet | | tailscale_send_message | Send a message to another agent (or "*" to broadcast) | | tailscale_check_messages | Check inbox for messages from other agents |

Team Coordination (opt-in: TS_ENABLE_TEAMS=1)

| Tool | Description | |------|-------------| | tailscale_team_create | Create a named team with this agent as lead | | tailscale_team_join | Join a team hosted by another agent | | tailscale_team_info | Show team membership and roles | | tailscale_task_create | Create a task on the shared task list | | tailscale_task_list | List tasks (filter by status: pending, in_progress, completed) | | tailscale_task_update | Claim, complete, update, or delete a task |

Example Usage

Once configured, Claude can access your tailnet services:

> Use tailscale_fetch to get the status of my internal API at http://api-server.tail1234.ts.net/health

> Check if my database server is reachable: tailscale_connect_test db.tail1234.ts.net port 5432

> What's my tailnet connection status?

Multi-Agent Coordination

Multiple Claude Code sessions on different machines can communicate and coordinate work over the tailnet.

Messaging — any agent can send messages to other cc-* peers:

> Find other agents on the tailnet
  → tailscale_agents

> Send a message to the backend agent
  → tailscale_send_message(to: "cc-ross-backend-a7b2", subject: "API ready", body: "...")

Team task coordination (requires TS_ENABLE_TEAMS=1) — a lead agent creates a team and shared task list. Teammates join and claim tasks:

Terminal 1 (Machine A — backend repo):
> "Create a team called api-migration"
  → tailscale_team_create(name: "api-migration")

> "Add tasks for the migration"
  → tailscale_task_create(subject: "Update /api/users response schema", ...)
  → tailscale_task_create(subject: "Update /api/auth token format", ...)

Terminal 2 (Machine B — frontend repo):
> "Join the api-migration team"
  → tailscale_team_join(lead_hostname: "cc-ross-backend-a7b2")

> "What tasks are available?"
  → tailscale_task_list(status: "pending")

> "Claim the users schema task"
  → tailscale_task_update(id: "task-1", action: "claim")
  → (works on it...)
  → tailscale_task_update(id: "task-1", action: "complete")

The lead holds the canonical task list in memory. Teammates interact with it over HTTP via the tailnet. If the lead goes offline, task operations fail cleanly — teammates can keep working on already-claimed tasks.

Configuration

| Environment Variable | Required | Default | Description | |---------------------|----------|---------|-------------| | TS_AUTHKEY | One of TS_AUTHKEY or TS_CLIENT_SECRET | — | Tailscale auth key (ephemeral recommended) | | TS_CLIENT_SECRET | One of TS_AUTHKEY or TS_CLIENT_SECRET | — | OAuth client secret (tskey-client-...). Preferred for automation/CI | | TS_TAGS | Required for OAuth | — | Comma-separated ACL tags (e.g., tag:claude-code,tag:dev) | | TS_HOSTNAME | No | cc-{user}-{context}-{rand} | Tailnet hostname override (random suffix always appended) | | TS_STATE_DIR | No | ~/.cache/claude-code-tailscale/{hostname} | State directory | | TS_CONTROL_URL | No | — | Custom control server (for Headscale) | | TS_EPHEMERAL | No | true | Register as ephemeral node | | TS_ENABLE_TEAMS | No | — | Set to 1 to enable team/task coordination tools | | TS_VERBOSE | No | — | Set to 1 for full tsnet debug logging |

Hostname format: cc-{user}-{context}-{random4} where {context} is the git repo name (or machine hostname if not in a repo) and {random4} is 4 random hex chars for uniqueness across concurrent sessions.

Architecture

Machine A (Lead)                              Machine B (Teammate)
+------------------------------------------+  +------------------------------------------+
| Claude Code Session A                    |  | Claude Code Session B                    |
| [Claude LLM] <-> [MCP Server (TS)]      |  | [Claude LLM] <-> [MCP Server (TS)]      |
|                    |                     |  |                    |                     |
|              [tshelper (Go)]             |  |              [tshelper (Go)]             |
|              |    |    |    |            |  |              |    |    |    |            |
|         SOCKS5  API  Agent  Team+Tasks  |  |         SOCKS5  API  Agent  (proxied)   |
|                      :9321  (local)     |  |                      :9321              |
+------------------------------------------+  +------------------------------------------+
                     |                                          |
                     +--------- Tailscale Tailnet --------------+

This plugin follows the same pattern as kong-tailscale-plugin:

  • Kong plugin: LuaJIT FFI → libtailscale → tailscale_loopback() → SOCKS5 → cosocket
  • This plugin: Go tsnet binary → SOCKS5 proxy → Node.js http.request with socks-proxy-agent

The Go helper (tshelper) uses tsnet.Server directly instead of libtailscale's C API, since we're already in Go. It runs three listeners:

  1. SOCKS5 proxy (localhost, random port) — routes HTTP traffic through the tailnet
  2. Control API (localhost, random port) — serves MCP tool requests (DNS, ping, devices, etc.)
  3. Agent listener (tailnet, port 9321) — inter-agent messaging, team join/leave, shared tasks

Key design decisions:

  • Lazy connection: Tailnet joins on first tool invocation to avoid wasting nodes
  • Ephemeral by default: Device auto-removes when the session ends, with explicit logout for instant cleanup
  • Unique hostnames: Each session gets a unique hostname (cc-{user}-{repo}-{rand}) to avoid collisions
  • OAuth + auth key support: Works with both TS_CLIENT_SECRET (OAuth) and TS_AUTHKEY (plain auth keys)
  • No system Tailscale required: tsnet embeds a full Tailscale node in the Go binary
  • Centralized task list: The team lead holds the canonical task store in memory; teammates proxy via HTTP. No distributed consensus needed
  • Feature-flagged teams: Team/task tools only register when TS_ENABLE_TEAMS=1, keeping the default tool set lean

License

Apache 2.0