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

@cityholdings/appium-node-cli

v0.4.0

Published

An interactive Appium shell powered by WebdriverIO

Readme

appium-node-cli

An interactive Appium client that feels like a database shell. It uses WebdriverIO in standalone mode and works with Android and iOS Appium drivers. It is a normal, deterministic CLI with no model provider or LLM SDK dependency.

Requirements

  • Node.js 20+
  • A reachable Appium server
  • The appropriate Appium driver installed on the server: uiautomator2 for Android or xcuitest for iOS
  • A connected/emulated device configured for that driver

Install

From this project:

npm install
npm run build
npm install -g .

After publishing, any machine can install it with:

npm install -g @cityholdings/appium-node-cli

Publishing (maintainers)

Publishing is automated by scripts/publish.sh, exposed as npm run release.

One-time setup:

  1. Create an Automation (or Granular, publish-enabled) token at npmjs.com → Access Tokens.

  2. Copy the token into a gitignored .env file (use .env.example as a template). The committed .npmrc reads it via ${NPM_TOKEN}, so no secret is ever stored in git:

    read -rs -p "Paste NPM token: " TOK && printf 'NPM_TOKEN=%s\n' "$TOK" > .env && unset TOK
    chmod 600 .env
  3. Make sure the @cityholdings npm org exists and your account can publish to it.

Release:

npm run release -- --dry-run   # build + rehearse, no upload
npm run release                # build + publish (public)

The script loads NPM_TOKEN from .env, runs the build, and runs npm publish. Bump the version first (npm version patch) if the current one is already on the registry — npm will not overwrite an existing version.

Connect

Android:

appium-cli \
  --server http://127.0.0.1:4723 \
  --cap platformName=Android \
  --cap appium:automationName=UiAutomator2 \
  --cap appium:deviceName=Android

iOS:

appium-cli \
  --server http://127.0.0.1:4723 \
  --cap platformName=iOS \
  --cap appium:automationName=XCUITest \
  --cap appium:deviceName=iPhone \
  --cap appium:udid=auto

For real projects, keeping capabilities in JSON is easier:

{
  "platformName": "Android",
  "appium:automationName": "UiAutomator2",
  "appium:deviceName": "Pixel",
  "appium:appPackage": "com.example",
  "appium:appActivity": ".MainActivity",
  "appium:noReset": true
}
appium-cli --caps-file ./capabilities.json

The URL may include a base path, such as http://localhost:4723/wd/hub for older server configurations.

Interactive commands

appium> source
appium> screenshot current.png
appium> find "~Login"
appium> click "~Login"
appium> type "id=com.example:id/email" "[email protected]"
appium> swipe 500 1500 500 400 600
appium> activate-app com.example
appium> contexts
appium> help

Selectors are passed directly to WebdriverIO. Accessibility IDs (~Login), Android resource IDs, XPath, iOS predicate strings, and class chains are supported by the corresponding Appium driver.

Attach to an existing session

appium-cli \
  --server http://127.0.0.1:4723 \
  --session-id YOUR_SESSION_ID

Attached sessions are left running by default. Add --delete-on-exit if the CLI should terminate the attached session. The CLI reads the existing session's capabilities from Appium before attaching, so native Android/iOS sessions work without repeating capabilities and without WebdriverIO probing the unsupported native /window endpoint.

Install the portable agent skill

The package includes a provider-neutral SKILL.md that teaches an agent how to inspect, act, verify, reuse sessions, and safely close them.

npx @cityholdings/appium-node-cli install-skill

By default this installs to both Claude and Codex (~/.claude/skills/appium-cli and ~/.codex/skills/appium-cli). Pass --target with a comma-separated list to choose where it goes:

npx @cityholdings/appium-node-cli install-skill --target claude,codex
npx @cityholdings/appium-node-cli install-skill --target claude
npx @cityholdings/appium-node-cli install-skill --target codex

Available targets:

| Target | Destination | | --- | --- | | claude | ~/.claude/skills/appium-cli (personal, all projects) | | claude-project | ./.claude/skills/appium-cli (current project only) | | codex | $CODEX_HOME/skills/appium-cli (default ~/.codex/skills) | | agents | ~/.agents/skills/appium-cli | | cursor | ./.cursor/skills/appium-cli | | windsurf | ./.windsurf/skills/appium-cli | | project | ./.agents/skills/appium-cli |

Use a custom destination for any other agent:

npx @cityholdings/appium-node-cli install-skill --path /path/to/agent/skills/appium-cli

Add --force to replace an existing copy; without it, a target that already has the skill is skipped (other targets still install). The skill itself is available at skills/appium-cli/SKILL.md in this package and does not depend on Codex, OpenAI, or any particular model.

Automation-friendly mode

An external AI agent or script can call one command at a time and consume JSON:

appium-cli --caps-file capabilities.json --command "source" --json

The result has a stable envelope:

{"ok":true,"command":"source","data":"<hierarchy>...</hierarchy>"}

Note that a one-shot invocation creates and closes a session. For multi-step automation, retain the new session:

appium-cli --caps-file capabilities.json \
  --command "status" --json --keep-session

Read data.sessionId, then attach for later commands:

appium-cli --session-id SESSION_ID --command "source" --json
appium-cli --session-id SESSION_ID --command 'click "~Login"' --json

Close the retained session when finished:

appium-cli --session-id SESSION_ID \
  --command "status" --json --delete-on-exit

With --json, interactive stdin/stdout is newline-delimited JSON without a human prompt, so another process can keep the CLI alive and exchange commands over pipes.

Security

Appium can control a real device. Keep the server on a trusted network, use authentication/TLS when exposed remotely, and avoid enabling Appium insecure features unless they are specifically needed.