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

worktree-device

v0.2.1

Published

Assign Android targets and Metro ports per git worktree

Readme

worktree-device

worktree-device is a local CLI for assigning Android targets and Metro ports per workspace. It is intended for projects that run multiple git worktrees or local checkouts at the same time.

The tool is project-agnostic. Projects opt in with a .worktree-device.toml file that declares which resources each command needs.

Requirements and support

  • macOS or Linux with a POSIX shell
  • Python 3 available as python3
  • Android SDK adb and emulator commands for Android target allocation
  • Xcode Command Line Tools on macOS when using the emulator label
  • A project-level .worktree-device.toml

npm Installation

Install an exact local development version so every checkout uses the same CLI:

npm install --save-dev --save-exact [email protected]
npm exec -- worktree-device doctor

Or install it globally:

npm install --global [email protected]
worktree-device doctor

Local standalone layout

Current local layout:

~/.local/bin/worktree-device
~/.config/worktree-device/config.toml
~/.local/state/worktree-device/state.sqlite
~/.local/share/worktree-device/README.md
~/.local/share/worktree-device/macos-emulator-label.swift
~/Applications/Worktree Device Overlay.app

~/.local/bin must be on PATH.

Concept

worktree-device does not infer behavior from command names. It only reads the command's declared resource requirements:

requires = []
  Run the command without allocation.

requires = ["metro.port"]
  Reserve a Metro port and inject METRO_PORT/RCT_METRO_PORT.

requires = ["android.target"]
  Reserve an Android target and inject ANDROID_SERIAL.

requires = ["android.target", "metro.port"]
  Reserve both, configure adb reverse, then run the command.

The state database stores reservations. It is not treated as absolute truth; each run rechecks adb devices, registered AVDs, active ports, and process state.

Global Config

Global defaults live at:

~/.config/worktree-device/config.toml

Example:

[android]
adb = "adb"
emulator = "emulator"
physical = "exclude"
boot_avd_if_needed = true
boot_timeout_sec = 180

[metro]
port_start = 8081
port_end = 8099

[state]
path = "~/.local/state/worktree-device/state.sqlite"

[ui]
emulator_label = true

On macOS, emulator_label displays a host-side badge above the emulator window when a command allocates both an emulator and a Metro port. The badge shows the git branch (or a short commit SHA for detached HEAD) and the Metro port. Its reload button sends Expo's reload message only to the badge's allocated Metro server. Set emulator_label to false to disable the badge.

The CLI builds a background-only Worktree Device Overlay.app in ~/Applications. The first run registers that named app with macOS and asks once for Accessibility permission. It does not appear in the Dock or menu bar. With permission enabled, the app follows emulator window events. If Accessibility window attributes are unavailable, it falls back to querying only the target CGWindowID at 10 Hz instead of scanning all windows. Because local builds use ad-hoc signing, macOS may request approval again after an update. The app exits when the owning worktree-device run process or emulator ends and hides the badge when the target window is not visible. Overlay failures never change the configured child command's exit status.

Project Config

Each participating project or worktree should add .worktree-device.toml at its workspace root:

version = 1

[workspace]
root = "git"

[android]
physical = "exclude"
boot_avd_if_needed = true

[metro]
port_start = 8081
port_end = 8099

[commands.androidDev]
run = "npm run android:dev:inner"
requires = ["android.target", "metro.port"]
adb_reverse = true

[commands.androidInstallDebug]
run = "npm run android:install:debug:inner"
requires = ["android.target"]

[commands.metro]
run = "npm run start:inner"
requires = ["metro.port"]

run is executed from the detected workspace root unless the command has its own cwd.

CLI

Run a configured command:

worktree-device run androidDev

Preview allocation without modifying state, booting an emulator, or running the child command:

worktree-device run androidDev --dry-run --json

Pass extra arguments to the child command:

worktree-device run androidDev -- --clear-cache

Print allocation environment:

worktree-device env androidDev --format shell
worktree-device env androidDev --format json

Inspect local state and Android tooling:

worktree-device list
worktree-device doctor
worktree-device doctor --fix

Release reservations:

worktree-device release
worktree-device release --all

Physical Devices

Physical devices are excluded by default. Override per run:

worktree-device run androidDev --physical allow
worktree-device run androidDev --physical prefer
worktree-device run androidDev --physical only
worktree-device run androidDev --serial <adb-serial>

Policy values:

exclude = default; emulator/AVD only
allow   = prefer emulator, fallback to physical
prefer  = prefer physical, fallback to emulator
only    = physical only

An explicit --serial is honored when that adb target is online.

Injected Environment

Child commands receive the relevant values:

ANDROID_SERIAL
AVD_NAME
METRO_PORT
RCT_METRO_PORT
WORKTREE_DEVICE_WORKSPACE_ID
WORKTREE_DEVICE_WORKSPACE_PATH
WORKTREE_DEVICE_ANDROID_SERIAL
WORKTREE_DEVICE_AVD_NAME
WORKTREE_DEVICE_METRO_PORT
WORKTREE_DEVICE_TARGET_TYPE

Project-local scripts should use these variables instead of implementing their own target allocator.

License

UNLICENSED. This package is not open source, and no permission is granted to use, copy, modify, or redistribute its source except as authorized by the copyright holder.