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

@kafitra/lynx-cli

v0.2.2

Published

Developer workflow CLI for Lynx Native Modules — autolink, run, prebuild, dev, doctor

Readme

@kafitra/lynx-cli

Developer workflow CLI for Lynx Native Modules.
From project generation to device launch — one tool for the full Android/iOS dev cycle.

Repository: github.com/kafitramarna/kafitra-lynx-native


Overview

lynx doctor          ← check your environment
lynx prebuild        ← generate Android host project
lynx link            ← wire native modules into Gradle
lynx run android     ← build + install + launch on device
lynx dev             ← start JS dev server
lynx run ios         ← build + launch on iOS simulator (macOS)

Installation

pnpm add -D @kafitra/lynx-cli
# or
npm install --save-dev @kafitra/lynx-cli

Add to package.json scripts:

{
  "scripts": {
    "android": "lynx run android --android-dir android-host",
    "dev": "lynx dev",
    "doctor": "lynx doctor"
  }
}

Commands

lynx doctor

Check your development environment before you start.

npx @kafitra/lynx-cli doctor

| Check | Required | Description | | ---------------- | -------- | -------------------------------- | | Node.js ≥ 18 | critical | Runtime version | | Java (JDK) ≥ 17 | critical | Android build toolchain | | adb | critical | Android Debug Bridge | | ANDROID_HOME | warning | Android SDK root | | Gradle wrapper | critical | gradlew + gradle-wrapper.jar | | Connected device | warning | At least one device/emulator |

Exits with code 1 if any critical check fails.


lynx prebuild

Generate a minimal clean Android host project from template.

npx @kafitra/lynx-cli prebuild --package com.example.myapp

| Option | Default | Description | | ----------------------- | --------- | ------------------------------------------ | | --package <id> | — | Required. Java package / applicationId | | --android-dir <path> | android | Output directory name | | --project-root <path> | cwd | Project root | | --force | off | Overwrite existing directory |

Generates:

android/
├── settings.gradle
├── build.gradle
├── gradlew / gradlew.bat
├── gradle/wrapper/gradle-wrapper.properties
└── app/
    ├── build.gradle          ← Lynx 3.6.0 deps pre-configured
    ├── proguard-rules.pro
    └── src/main/
        ├── AndroidManifest.xml
        ├── assets/            ← put main.lynx.bundle here
        └── java/com/example/myapp/
            ├── LynxApplication.java
            ├── MainActivity.java
            ├── LynxTemplateProvider.java
            └── LynxAutolinkRegistry.java

Auto-runs lynx link after generation to wire up any installed modules.

Note: gradle-wrapper.jar is auto-downloaded from GitHub if missing — no manual step needed.

Note: Generated MainActivity extends AppCompatActivity — required for CameraX lifecycle binding and runtime permission dialogs.


lynx link

Scan node_modules, generate LynxAutolinkRegistry.java, and patch settings.gradle, app/build.gradle, and AndroidManifest.xml.

npx @kafitra/lynx-cli link [options]

| Option | Default | Description | | ----------------------- | ----------------------------- | ----------------------------------------------------- | | --project-root <path> | cwd | Root of the host project (where node_modules lives) | | --android-dir <path> | android | Android directory name | | --java-package <name> | inferred from applicationId | Java package for the registry class |

All patch operations are idempotent — running the command twice produces the same result.

Steps performed:

  1. Scan node_modules for lynx.module.json packages
  2. Generate LynxAutolinkRegistry.java
  3. Inject settings.gradle project includes
  4. Inject app/build.gradle dependencies
  5. Inject AndroidManifest.xml <uses-permission> entries (from each module's permissions field)

One-time Application class setup:

private void initLynxEnv() {
    LynxEnv.inst().init(this, null, null, null);
    LynxAutolinkRegistry.registerAll(); // ← call once
}

lynx run android

Auto-link → build APK → install → launch. One command replaces all manual steps. `

npx @kafitra/lynx-cli run android [options]

| Option | Default | Description | | ----------------------- | ------------ | ----------------------------- | | --project-root <path> | cwd | Root of the host project | | --android-dir <path> | android | Android directory name | | --device <serial> | first device | Target specific device serial | | --no-link | off | Skip auto-running lynx link |

What it does:

  1. Runs lynx link (unless --no-link)
  2. Checks if dev server is running on port 3000; starts it in a new terminal if not
  3. Detects connected devices via adb devices; auto-launches AVD if none found
  4. Copies dist/main.lynx.bundle → assets (if missing), then runs gradlew installDebug
  5. Sets up adb reverse tcp:3000 tcp:3000
  6. Launches app via adb shell am start

Examples:

# Standard
npx @kafitra/lynx-cli run android

# Custom android dir (monorepo)
npx @kafitra/lynx-cli run android --android-dir android-host

# From repo root
npx @kafitra/lynx-cli run android --project-root apps/demo --android-dir android-host

# Target specific device
npx @kafitra/lynx-cli run android --device emulator-5554

lynx dev

Start the JS dev server and display bundle URLs for all network interfaces.

npx @kafitra/lynx-cli dev [options]

| Option | Default | Description | | ----------------------- | ------- | -------------------------------------- | | --project-root <path> | cwd | Project root containing package.json | | --port <number> | 3000 | Dev server port |

Auto-detects package manager (pnpm, yarn, or npm) and spawns run dev.
Prints all bundle URLs for localhost and LAN. Ctrl+C shuts down cleanly.

→  Starting dev server…

ℹ  Bundle URLs:
ℹ    Local:   http://localhost:3000/main.lynx.bundle
ℹ    Network: http://192.168.1.42:3000/main.lynx.bundle

ℹ  Android port forwarding:
ℹ    adb reverse tcp:3000 tcp:3000

lynx run ios

Build and launch on iOS simulator. macOS only.

npx @kafitra/lynx-cli run ios --bundle-id com.example.myapp

| Option | Default | Description | | ----------------------- | ------- | -------------------------------------------- | | --project-root <path> | cwd | Root of the host project | | --ios-dir <path> | ios | iOS directory name | | --bundle-id <id> | — | iOS bundle identifier (for simulator launch) | | --no-pod-install | off | Skip pod install |

What it does:

  1. Guards non-macOS systems
  2. Validates ios/*.xcworkspace exists
  3. Runs pod install
  4. Builds via xcodebuild -sdk iphonesimulator
  5. Launches on booted simulator via xcrun simctl launch

Monorepo usage

# From repo root, targeting a specific app
npx @kafitra/lynx-cli run android \
  --project-root apps/demo \
  --android-dir android-host

# Or via workspace script
pnpm --filter @your/demo run android

How a module declares itself

Each Lynx Native Module must include a lynx.module.json at its package root:

{
  "name": "LynxDeviceInfo",
  "android": {
    "moduleClass": "com.kafitra.lynxdeviceinfo.LynxDeviceInfoModule",
    "sourceDir": "android"
  }
}

See @kafitra/lynx-autolink for the full schema reference.


Troubleshooting

No Android devices or emulators found
→ Connect a device with USB debugging enabled, or start an AVD emulator.

Gradle wrapper not found
→ Run lynx prebuild --package <id> to generate the project, or
→ Run gradle wrapper --gradle-version 8.2 inside your Android directory.

pod install failed: CocoaPods not found
sudo gem install cocoapods

adb: command not found
→ Install Android SDK Platform-Tools and add to PATH.

ANDROID_HOME not set
→ Set it to your SDK path. Run lynx doctor for exact instructions.

Build fails with AbstractMethodError
→ Do not register LynxHttpService — it is incompatible with lynx:3.6.0 core.


Other flags

lynx --version   # print CLI version
lynx --help      # print usage

Requirements

  • Node.js ≥ 18
  • JDK ≥ 17 (for Android builds)
  • Android SDK + adb in PATH
  • AGP ≥ 7.x, Gradle ≥ 8.x
  • Each Lynx Native Module must have lynx.module.json

License

MIT