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

clsniff

v1.3.4

Published

Zero-configuration HTTP/HTTPS traffic sniffer for command-line tools like claude

Downloads

308

Readme

clsniff

CI npm license node

A zero-configuration HTTP/HTTPS traffic sniffer for command-line tools.

Wrap any command with clsniff and every HTTP/HTTPS request it makes will be captured and saved to a JSON file — including full request/response headers and bodies (SSE responses are captured as an array of parsed events).

clsniff demo

Prerequisites

How it works

clsniff starts mitmdump(mitmproxy's headless mode) as a subprocess and launches your command as a child process with environment variables injected so it routes traffic through the proxy and trusts its CA certificate.

When a request passes through the proxy, clsniff:

  1. Captures the full request (method, URL, headers, body)
  2. Forwards it to the real server without modification
  3. Captures the full response (status, headers, body or SSE events)
  4. Forwards the response to the child process without modification
  5. Writes a JSON file with both sides of the exchange

The child process is completely unaware of the interception. Its stdin, stdout, and stderr are passed through directly.

Getting started

# Run without installing
npx -y clsniff@latest --viewer -- claude

# Or install globally
npm install -g clsniff
clsniff --viewer -- claude

Intercepted requests are saved to ~/.clsniff/ as JSON files, one per request/response pair.

Usage

clsniff [options] -- <command> [args...]

The -- separator is required to separate clsniff options from the wrapped command.

Options

| Flag | Description | Default | |---|---|---| | --output-dir <path> | Directory where session log folders are created | ~/.clsniff | | --name <name> | Name for the session folder instead of the auto-generated timestamp | (timestamp) | | --port <number> | Port for the local proxy (0 = OS auto-assign) | 0 | | --mask-headers <names> | Comma-separated header names to redact in JSON output. Can be repeated. | (none) | | --exclude <hosts> | Comma-separated hosts to bypass interception entirely (NO_PROXY format). Bypassed hosts get a direct TCP tunnel — no MITM, no logging. Can be repeated. Example: example.com,.datadoghq.com | (none) | | --install-cert | Install mitmproxy's CA certificate in the system trust store | (off) | | --viewer | Start the web-based log viewer | (off) | | --no-open | Do not auto-open the browser when starting the viewer | (off) |

--viewer includes a Claude tab with enhanced support for parsing and displaying Claude-specific request/response formats, according to https://platform.claude.com/docs/en/api/messages/create

Examples

Intercept all traffic:

clsniff -- claude --dangerously-skip-command

Redact the API key:

clsniff --mask-headers "authorization" -- claude

Bypass telemetry hosts:

clsniff --exclude ".datadoghq.com" -- claude

Intercept traffic and open the viewer:

clsniff --viewer --mask-headers "authorization" -- claude

Browse existing sessions (standalone viewer, no command needed):

clsniff --viewer

Start the viewer without auto-opening the browser:

clsniff --viewer --no-open -- claude

Output format

Each clsniff invocation creates a new timestamped folder under ~/.clsniff/ (one folder per run):

~/.clsniff/
  2026-04-09T14-30-00-000Z/
    1744200600123_1.json
    1744200601456_2.json
    clsniff.log

clsniff.log contains timestamped internal messages (proxy startup, per-request entries, errors).

Each JSON file contains one request/response pair:

{
  "id": 20,
  "timestamp": "2026-04-09T14:53:19.651Z",
  "duration_ms": 1936,
  "request": {
    "method": "POST",
    "url": "https://api.anthropic.com/v1/messages?beta=true",
    "headers": {
      "authorization": "Bearer sk-ant-...",
      "content-type": "application/json",
      "anthropic-version": "2023-06-01"
    },
    "body": {
      "model": "claude-sonnet-4-6",
      "stream": true,
      "messages": [
        { "role": "user", "content": "Hello" }
      ]
    }
  },
  "response": {
    "status": 200,
    "headers": {
      "content-type": "text/event-stream; charset=utf-8",
      "request-id": "req_011CZpbpzFt2wEZFQmZAyayD"
    },
    "body": [
      { "event": "message_start", "data": { "type": "message_start", ... } },
      { "event": "content_block_delta", "data": { "type": "content_block_delta", ... } },
      { "event": "message_stop", "data": { "type": "message_stop" } }
    ]
  }
}

Certificate management

On first run, mitmproxy generates a CA (Certificate Authority) key pair and stores it in ~/.mitmproxy/:

~/.mitmproxy/
  mitmproxy-ca.pem          (CA key + certificate)
  mitmproxy-ca-cert.pem     (CA certificate, PEM — used by NODE_EXTRA_CA_CERTS)
  mitmproxy-ca-cert.cer     (CA certificate, DER — used by certutil on Windows)
  mitmproxy-ca-cert.p12     (CA certificate, PKCS12)
  mitmproxy-dhparam.pem     (DH parameters)

These files are generated once and reused across all sessions and tools.

Trusting the CA certificate

On first run (when ~/.mitmproxy/mitmproxy-ca-cert.pem does not yet exist), clsniff automatically tries to install the CA certificate in your system trust store. You can also trigger this manually at any time with --install-cert.

| Platform | Action | |---|---| | Windows | Runs certutil -addstore -user Root mitmproxy-ca-cert.cer. A Windows security dialog will appear asking for confirmation. | | macOS | Prints the sudo security add-trusted-cert ... command to run manually. | | Linux | Prints instructions to add the cert to your distro's CA bundle. |

Regardless of system-level trust, NODE_EXTRA_CA_CERTS, SSL_CERT_FILE, and REQUESTS_CA_BUNDLE are always set in the child process environment to ensure Node.js, Python, and OpenSSL-based tools trust the proxy CA automatically.

Note: SSL_CERT_FILE replaces the system CA bundle for the child process. If you use --exclude to bypass certain hosts, those connections reach the real server but will fail TLS verification because the real CAs are no longer trusted in SSL_CERT_FILE. In that case, install the cert system-wide (via --install-cert) so the system CA bundle is used instead.

Environment variables

clsniff injects the following variables into the child process before launching it.

Proxy routing:

  • HTTP_PROXY, HTTPS_PROXY, http_proxy, https_proxy — set to http://127.0.0.1:<port>
  • NO_PROXY, no_proxy — set to localhost,127.0.0.1

CA trust:

Development

git clone https://github.com/panicoenlaxbox/clsniff.git
cd clsniff
npm install

# Run against a real command
npm run dev -- -- claude

# Run with the viewer
npm run dev -- --viewer -- claude

# Standalone viewer with hot reload
npm run dev:hot