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

bare-appletv-remote

v0.2.1

Published

Apple TV remote control library for the Bare runtime

Readme

bare-appletv-remote

Apple TV remote control library for the Bare runtime

Controls Apple TV via the Companion Link protocol — the same protocol used by the iOS Remote app. Handles discovery, pairing, session encryption, and remote commands including navigation, playback, touch gestures, and power.

Install

npm install bare-appletv-remote

Usage

As a library

const AppleTVRemote = require('bare-appletv-remote')

// First run: scans the network, pairs (showing a PIN on the TV screen),
// and saves credentials to ~/.appletv-credentials.json automatically.
// Subsequent runs: loads credentials from disk silently.
const remote = new AppleTVRemote({
  onpin: async () => {
    // called only when pairing is needed — return the PIN shown on screen
    return myPromptFunction('Enter the PIN shown on the Apple TV: ')
  }
})

await remote.ready()

// Navigation
await remote.up()
await remote.down()
await remote.left()
await remote.right()
await remote.click()      // select focused item
await remote.menu()       // menu / back button
await remote.back()       // alias for menu()

// Playback
await remote.playPause()

// Volume
await remote.volumeUp()
await remote.volumeDown()

// Power
await remote.sleep()
await remote.wake()       // Wake-on-LAN (requires Ethernet on the Apple TV)

// Touch gestures — coordinates are on a 0–1000 × 0–1000 surface
await remote.swipe('right')           // fast-forward
await remote.swipe('left')            // rewind
await remote.swipe('right', { distance: 500, steps: 20 })

// Low-level touch — useful for custom UI or continuous scrubbing
await remote.touchBegin(500, 500)
await remote.touchMove(700, 500)
await remote.touchEnd(700, 500)

await remote.close()

The session connection is established during ready() and kept open for the lifetime of the remote. If the Apple TV drops the connection (e.g. after a long idle or on sleep), it is re-established transparently on the next command.

Options

| Option | Type | Default | Description | | ----------------- | --------------------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------- | | onpin | () => Promise<string> \| string | — | Called when pairing is needed. Return the PIN shown on screen. Required for first-time pairing. | | credentials | Credentials | — | Pass credentials directly, bypassing disk. | | credentialsFile | string | ~/.appletv-credentials.json | Override the credentials file path. | | host | string | — | Skip mDNS discovery and connect directly to this IP address. | | port | number | — | Port to use when host is set. | | idleTimeout | number | 0 | Milliseconds of inactivity before the session is closed. Default keeps it open indefinitely. | | debug | boolean | false | Log protocol traffic. |

Events

remote.on('paired', () => console.log('Paired and saved.'))
remote.on('ready', () => console.log('Ready.'))
remote.on('close', () => console.log('Closed.'))

CLI

npm install -g bare-appletv-remote
# First run: scans, pairs, saves credentials
appletv pair

# Navigation
appletv up | down | left | right | click

# Playback & volume
appletv play
appletv volup | voldown

# Menu
appletv back

# Power
appletv sleep
appletv wake

Pairing troubleshooting

When pairing is initiated the Apple TV should display a PIN automatically. If nothing appears on screen:

  1. Wake the TV first. The PIN dialog only appears when the TV is active. Press a button on the physical Siri Remote to wake it, then run pair again.

  2. The PIN appears as an overlay anywhere. It will appear over full-screen apps, the home screen, or even during video playback — you do not need to navigate to a specific screen first.

  3. Enable remote access. On the Apple TV go to Settings → AirPlay & HomeKit and make sure Allow Access is not set to No One.

  4. Remove a stale pairing. If the TV silently rejects the request (no PIN shown, but the handshake completes), a leftover pairing entry may be blocking it. On the Apple TV go to Settings → AirPlay & HomeKit → Remote App and Devices (or Settings → Remotes and Devices → Remote App and Devices) and remove any existing entry for this device, then pair again.

  5. Delete local credentials and retry. If ~/.appletv-credentials.json exists from a previous attempt that did not complete, delete it before running pair again.

Advanced: scan and pair manually

const AppleTVRemote = require('bare-appletv-remote')

// Scan the network for Apple TVs
const devices = await AppleTVRemote.scan()
console.log(devices[0].name, devices[0].address)

// Pair with a specific device
const credentials = await AppleTVRemote.pair(devices[0], async () => getPin())

// Use the credentials
const remote = new AppleTVRemote({ credentials })
await remote.up()
await remote.close()

Protocol

Uses the Companion Link protocol (_companion-link._tcp mDNS service) with HAP (HomeKit Accessory Protocol) security:

  • Pairing: SRP-6a (3072-bit) + Ed25519 long-term keys + ChaCha20-Poly1305
  • Sessions: X25519 ephemeral DH + HKDF-SHA512 session keys
  • Commands: Encrypted OPACK messages with HID event payloads
  • Touch: _touchUpdate messages on a 1000×1000 virtual touchpad surface
  • Wake: UDP Wake-on-LAN magic packet (MAC from mDNS rpAD TXT record)

Crypto via sodium-universal.

Acknowledgements

License

MIT