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

easypresent

v0.1.1

Published

Lightweight, secure, local-network remote-control system. Control your computer from any browser on the same network.

Readme

EasyPresent

Lightweight, secure, local-network remote control. Control your computer from any browser on the same network — no cloud, no app install, no account.

Run one command, scan a QR code with your phone, and you get a live view of your screen — all over your local network.

npm install -g easypresent
easypresent
────────────────────────────────────────────────
  EasyPresent
  Local-network remote control
────────────────────────────────────────────────

  Local:     http://localhost:3000
  Network:   http://192.168.1.25:3000
  Pair code: AB3XK7

  Scan this QR code with your phone:
    ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
    ...

  Waiting for connection...

Quick start

npm install -g easypresent
easypresent

Or without installing:

npx easypresent

Then:

  1. Note the Network URL and pair code in the terminal (or scan the QR code).
  2. Open the URL on your phone/tablet/laptop browser.
  3. Enter the pair code (scanning the QR code fills it in automatically).
  4. You're connected — you'll see your host screen live.

How it works

Run EasyPresent  →  Scan QR  →  Phone opens browser  →  Pair with code  →  See host screen  →  Control host

EasyPresent runs entirely on your machine. No cloud server. No relay. No account. Nothing leaves your local network.

Supported platforms

| Capability | Windows | macOS | Linux | | ----------------- | :-----: | :---: | :---: | | Screen capture | ✅ | ✅ | ✅ | | Keyboard injection | ✅ | ✅ | ✅ (X11) | | Mouse injection | ✅ | ✅ | ✅ (X11) | | Web UI | ✅ | ✅ | ✅ |

  • Windows: works out of the box.
  • macOS: requires Accessibility and Screen Recording permissions (see below).
  • Linux: works on X11. Wayland support is limited; run the host under XWayland for best results.

OS permissions

macOS

Grant the application running EasyPresent (usually Terminal, iTerm2, or VS Code) the following permissions in System Settings → Privacy & Security:

  • Accessibility — required for keyboard and mouse injection.
  • Screen Recording — required for screen capture.

After toggling these on, restart the app running EasyPresent.

Windows

No special permissions required. Some antivirus software may flag synthetic input; allow EasyPresent if prompted.

Linux

  • X11: works without extra setup for the user's own session.
  • Wayland: input injection and screen capture are restricted. Use XWayland or an X session.

CLI options

easypresent [options]

Options:
  -p, --port <port>          Port to listen on (default: 0 = auto-select)
  -H, --host <host>          Host/interface to bind (default: 0.0.0.0)
      --no-screen            Disable screen capture/streaming
      --no-input             Disable keyboard/mouse input injection
      --token <token>        Use an explicit pairing token
      --max-devices <n>      Maximum connected devices (default: 1)
      --multi-controller     Allow multiple devices to control at once
      --fps <n>              Target frames per second (default: 30)
      --quality <n>          JPEG quality 1-100 (default: 70)
      --max-width <px>       Maximum stream width (default: 1920)
      --tls-cert <path>      Path to TLS cert (enables HTTPS)
      --tls-key <path>       Path to TLS key (enables HTTPS)
      --tls-ca <path>        Optional TLS CA bundle
      --allow-origin <o...>  Allowed origins (repeatable)
      --no-qr                Do not print a QR code
  -v, --verbose              Verbose logging
  -h, --help                 Show help

Examples:

easypresent --port 3000
easypresent --host 0.0.0.0 --fps 60 --quality 85
easypresent --no-screen          # input only (great for presentations)
easypresent --no-input           # view only
easypresent --token MYCODE       # fixed pair code
easypresent --tls-cert cert.pem --tls-key key.pem

If the requested port is taken, EasyPresent automatically picks an available one.

The remote web interface

The UI is mobile-first, dark, and touch-optimized. It shows a live view of your host screen:

  • Live view of the host display.
  • Scales to your device, supports fullscreen and landscape lock.
  • Automatic reconnection and clear connection/stream status (loading, failure, reconnecting).

Programmatic API

import { EasyPresent } from "easypresent";

const remote = new EasyPresent({
  port: 3000,
  fps: 60,
  quality: 80,
  // noScreen: false,
  // noInput: false,
  // maxDevices: 2,
  // allowMultipleControllers: false,
});

await remote.start();

remote.on("deviceConnected", (device) => {
  console.log("connected:", device.name, device.remoteAddress);
});
remote.on("deviceDisconnected", (device) => console.log("gone:", device.name));
remote.on("key", ({ msg, device }) => console.log("key", msg.key, msg.action, "from", device.name));
remote.on("mouse", ({ msg, device }) => console.log("mouse", msg, "from", device.name));
remote.on("error", (err) => console.error(err));

// Inspect state
console.log(remote.devices);     // DeviceInfo[]
console.log(remote.token);       // current pairing token

// Manage devices
remote.revokeDevice(deviceId);
remote.rotateToken();

// Stop
await remote.stop();

EasyPresentOptions

| Option | Type | Default | Description | | ------ | ---- | ------- | ----------- | | port | number | 0 | Port to listen on; 0 auto-selects. | | host | string | 0.0.0.0 | Interface to bind. | | noScreen | boolean | false | Disable screen capture/streaming. | | noInput | boolean | false | Disable input injection. | | verbose | boolean | false | Verbose logging. | | token | string | auto | Explicit pairing token. | | maxDevices | number | 1 | Max concurrent devices. | | allowMultipleControllers | boolean | false | Let multiple devices control. | | fps | number | 30 | Target stream FPS. | | quality | number | 70 | JPEG quality 1–100. | | maxWidth | number | 1920 | Max stream width. | | tls | object | — | { cert, key, ca? } to enable HTTPS. | | allowedOrigins | string[] | [] | Origin allow-list. | | noQr | boolean | false | Suppress QR code in CLI. | | webRoot | string | bundled | Path to web UI assets. |

Events

| Event | Payload | Description | | ----- | ------- | ----------- | | started | { port, host, url } | Server is listening. | | stopped | — | Server stopped. | | deviceConnected | DeviceInfo | A device paired. | | deviceDisconnected | DeviceInfo | A device left or was revoked. | | key | { msg, device } | A key event was received. | | text | { msg, device } | A text event was received. | | mouse | { msg, device } | A mouse event was received. | | stream | { msg, device } | A stream control message. | | error | Error | A non-fatal error. |

Security

EasyPresent is designed for trusted local networks:

  • Pairing token — a short, per-session code is required before any control is accepted.
  • No unauthenticated access — connections that don't authenticate within 10 seconds are dropped.
  • Single controller by default — only one device may inject input; additional devices can observe. Use --multi-controller to override.
  • Device limits — --max-devices caps concurrent connections.
  • Strict message validation — unknown message types and fields are rejected/stripped.
  • Rate limiting — per-connection token buckets prevent flooding.
  • Origin validation — optional --allow-origin allow-list.
  • No remote shell — there is no command execution endpoint.
  • Optional HTTPS — --tls-cert/--tls-key for encrypted LAN transport.
  • No cloud — nothing is sent to any external server.

Troubleshooting

No LAN address detected. Make sure you're connected to Wi-Fi/Ethernet. You can still connect via http://localhost:<port> on the host.

Port X in use. EasyPresent auto-selects another port. Use --port 0 to always auto-select.

macOS: keys/mouse don't do anything. Grant Accessibility permission to the app running EasyPresent and restart it.

macOS: screen is black/blank. Grant Screen Recording permission and restart the app.

Linux/Wayland: input or capture fails. Run under XWayland or an X11 session.

Device can't connect. Confirm the phone is on the same Wi-Fi as the computer and that the network allows local device-to-device traffic (some guest/isolated networks block it).

Verbose logs / stack traces. Run with --verbose or set EASYPRESENT_DEBUG=1 for a full stack trace on startup failures.

License

MIT — see LICENSE.