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

@kud/androidtv-remote

v0.1.2

Published

Control Android TV / Google TV devices over the Android TV Remote v2 protocol

Readme

TypeScript Node.js npm MIT

Control Android TV / Google TV devices over the Android TV Remote v2 protocol

FeaturesQuick StartAPI ReferenceDevelopment

A modern TypeScript/ESM implementation of the Android TV Remote v2 protocol — pair with a device over TLS, then send keys, launch apps, and inject text directly from Node.

🌟 Features

  • 🔑 First-class pairing — handles the full certificate-based TLS pairing flow and persists credentials for reconnect
  • ⌨️ Native text inputsendText() uses IME injection to type arbitrary strings, no keycode mapping required
  • 📺 Full key control — send any Android key via RemoteKeyCode constants (navigation, media, DPAD, volume, and more)
  • 📡 State events — subscribe to powered, volume, current_app, and unpaired with typed payloads
  • 🪶 Lean dependenciescrypto-js, systeminformation, and core-js dropped; relies only on node-forge and protobufjs
  • 🔇 Silent by default — all internal logging is suppressed unless debug: true is set, so it fits cleanly inside a larger application
  • 🏷️ Typed API — full TypeScript types exported; on(), once(), and emit() are all narrowed to the event map

🚀 Quick Start

npm install @kud/androidtv-remote

Pair a new device

import { createAndroidRemote } from "@kud/androidtv-remote"

const remote = createAndroidRemote("192.168.1.42")

remote.on("secret", () => {
  // The TV shows a pairing PIN — read it from stdin and submit
  remote.sendCode("123456")
})

remote.on("ready", () => {
  console.log("paired and connected")
  remote.sendPower()
})

await remote.start()

// Persist the certificate so you skip pairing next time
const cert = remote.getCertificate()

Reconnect with a saved certificate

import { createAndroidRemote } from "@kud/androidtv-remote"

const remote = createAndroidRemote("192.168.1.42", {
  cert: { key: savedKey, cert: savedCert },
})

remote.on("ready", () => {
  remote.sendText("Hello, TV!")
})

await remote.start()

📖 API Reference

createAndroidRemote(host, options?)

Factory function that returns an AndroidRemote instance — an EventEmitter extended with control methods.

import { createAndroidRemote } from "@kud/androidtv-remote"

const remote = createAndroidRemote("192.168.1.42", options)

Options

| Option | Type | Default | Description | | -------------- | ------------------------------- | -------------------- | ------------------------------------------------------------- | | cert | { key: string; cert: string } | — | Previously obtained certificate. Skips pairing when provided. | | pairing_port | number | 6467 | TCP port for the pairing handshake. | | remote_port | number | 6466 | TCP port for the remote control session. | | service_name | string | "androidtv-remote" | Name sent to the TV during pairing. | | manufacturer | string | — | Device manufacturer reported during pairing. | | model | string | — | Device model reported during pairing. | | debug | boolean | false | Enable verbose internal logging. |

Methods

| Method | Returns | Description | | ------------------------------ | ------------------ | ------------------------------------------------------------- | | start() | Promise<boolean> | Connect to the TV. Triggers pairing if no certificate is set. | | sendCode(code) | boolean | Submit the PIN displayed on the TV during pairing. | | sendKey(keyCode, direction?) | void | Send a key press. Use RemoteKeyCode constants. | | sendPower() | void | Toggle the TV power state. | | sendAppLink(link) | void | Launch an app via its deep-link URI. | | sendText(text) | void | Inject arbitrary text via IME (no keycode mapping). | | getCertificate() | Certificate | Return the current { key, cert } pair for persistence. | | stop() | void | Close all connections. |

Events

| Event | Payload | Fired when | | ------------- | ---------------------------------------------------- | --------------------------------------------------- | | secret | — | The TV is showing a pairing PIN. Call sendCode(). | | ready | — | Connected and ready for commands. | | powered | boolean | TV power state changed. | | volume | { level: number; maximum: number; muted: boolean } | Volume state changed. | | current_app | string | Foreground app changed (package name). | | unpaired | — | The TV rejected or revoked the certificate. | | error | Error | A protocol-level error occurred. |

RemoteKeyCode

An enum of Android key codes. Common entries:

import { RemoteKeyCode } from "@kud/androidtv-remote"

remote.sendKey(RemoteKeyCode.KEYCODE_HOME)
remote.sendKey(RemoteKeyCode.KEYCODE_BACK)
remote.sendKey(RemoteKeyCode.KEYCODE_DPAD_UP)
remote.sendKey(RemoteKeyCode.KEYCODE_MEDIA_PLAY_PAUSE)
remote.sendKey(RemoteKeyCode.KEYCODE_VOLUME_UP)

RemoteDirection

Direction constants for sendKey() — defaults to SHORT (a normal press). Use START_LONG / END_LONG to bracket a long press:

import { RemoteKeyCode, RemoteDirection } from "@kud/androidtv-remote"

remote.sendKey(RemoteKeyCode.KEYCODE_DPAD_UP) // SHORT by default
remote.sendKey(RemoteKeyCode.KEYCODE_DPAD_DOWN, RemoteDirection.START_LONG)
remote.sendKey(RemoteKeyCode.KEYCODE_DPAD_DOWN, RemoteDirection.END_LONG)

setDebug(enabled)

Enable or disable verbose logging globally (affects all instances):

import { setDebug } from "@kud/androidtv-remote"

setDebug(true)

🔧 Development

androidtv-remote/
├── src/
│   ├── index.ts                        # Public API and factory
│   ├── types.ts                        # Shared TypeScript types
│   ├── device-info.ts                  # Device metadata sent during pairing
│   ├── logger.ts                       # Debug-gated logger
│   ├── certificate/
│   │   └── certificate-generator.ts   # TLS cert generation via node-forge
│   ├── pairing/
│   │   ├── pairing-manager.ts         # Pairing session state machine
│   │   ├── pairing-message-manager.ts
│   │   └── pairingmessage.proto
│   └── remote/
│       ├── remote-manager.ts          # Remote control session
│       ├── remote-message-manager.ts  # Key/text encoding
│       └── remotemessage.proto
└── dist/                              # Compiled output (tsup)
git clone https://github.com/kud/androidtv-remote.git
cd androidtv-remote
npm install
npm run build

Scripts

| Script | Description | | --------------------- | -------------------------------------- | | npm run build | Compile TypeScript to dist/ via tsup | | npm run build:watch | Recompile on file changes | | npm run typecheck | Type-check without emitting | | npm test | Run tests with tsx | | npm run clean | Remove dist/ |

🏗 Tech Stack

| Package | Role | | ------------ | --------------------------------------------------- | | node-forge | TLS certificate generation and mutual TLS | | protobufjs | Encode/decode Android TV Remote v2 protocol buffers | | tsup | Zero-config TypeScript bundler | | tsx | TypeScript test runner |

Credits

Derived from androidtv-remote by louis49 (MIT). The reverse-engineered Android TV Remote v2 protocol and .proto schemas originate from that project. This library is a TypeScript rewrite with a functional API, native text input support, and a leaner dependency footprint.


MIT © kud