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

@newinstance/bugwatch-cli

v0.1.1

Published

BugWatch CLI — upload Apple dSYM debug symbols for native crash symbolication.

Readme

@newinstance/bugwatch-cli

Upload Apple .dSYM debug symbols to BugWatch so native iOS and macOS crashes are symbolicated — function names, file paths, and line numbers instead of raw memory addresses. One command, CI-friendly, runs anywhere Node 18+ is available.

npx @newinstance/bugwatch-cli symbols upload MyApp.xcarchive \
  --release 1.4.2 --build-number 318

Requirements

  • Node.js 18 or later (ESM-native package)
  • A macOS machine or macOS CI runner — dSYM files are produced by Xcode
  • A BugWatch API key with the symbols:upload permission scope (see Getting an API key)

Install

No install needed — run it on demand with npx (requires Node 18+):

npx @newinstance/bugwatch-cli symbols upload <path> ...

Or install it globally — the bin name is bugwatch, so this exposes bugwatch on $PATH:

npm install -g @newinstance/bugwatch-cli
bugwatch symbols upload <path> ...

Build from source (contributors / unreleased revisions)

To run a local build (e.g. an unreleased change, or an air-gapped runner without npm access):

# from the repo root
cd bugwatch-cli
npm install        # or: bun install
npm run build      # outputs dist/ + bin/bugwatch.mjs
node bin/bugwatch.mjs symbols upload <path> ...

Getting an API key

  1. Open the merchant dashboard for your organisation.
  2. Navigate to API Keys (project-level or org-level depending on your plan).
  3. Create a secret key (sk_test_… / sk_live_…).
  4. Make sure the key has the symbols:upload permission scope assigned. The key validator rejects requests from keys that lack this scope.
  5. Copy the full value — it is shown only once. Store it as a CI secret (never hard-code it or commit it to source control).

The key is sent on every request as the x-api-key: <keyId>:<secret> header. It is never placed in the URL or logged; the CLI prints a redacted form (sk_l…3456) for human confirmation only.


Authentication

| Method | How | |---|---| | CLI flag | --token <keyId>:<secret> | | Environment variable | BUGWATCH_AUTH_TOKEN=<keyId>:<secret> |

The environment variable is preferred for CI — set it as a secret in your pipeline so it is not visible in build logs.

The API endpoint can similarly be overridden via --api-url or BUGWATCH_API_URL (default: https://api.newinstance.cloud).


Command reference

bugwatch symbols upload <path> [options]

<path> is the only required positional argument. All metadata flags are optional but recommended — the debug UUID embedded in every dSYM is the authoritative match criterion; metadata improves search and display in the dashboard.

Flag reference

| Flag | Env | Type | Default | Description | |---|---|---|---|---| | --token | BUGWATCH_AUTH_TOKEN | string | — | Required. API secret key (keyId:secret). Never ship to a browser or app binary. | | --api-url | BUGWATCH_API_URL | string | https://api.newinstance.cloud | BugWatch REST API base URL. | | --platform | — | enum | ios | Target platform: ios · macos · tvos · watchos · visionos · catalyst | | --release | — | string | — | Marketing version (e.g. 1.4.2). Improves dashboard discoverability. | | --build-number | — | string | — | Build number (e.g. 318). Used to disambiguate the same version string across builds. | | --bundle-id | — | string | — | App bundle identifier (e.g. com.example.MyApp). | | --distribution | — | enum | — | app-store · testflight · adhoc · enterprise · development | | --environment | — | string | — | Environment tag (e.g. production, staging). | | --commit | — | string | — | Source commit SHA. Links crash reports to a specific code revision. | | --upload-source | — | string | cli | Tag identifying the upload origin (e.g. ci, fastlane, run-script). Visible in the dashboard. |

Accepted input formats

| Input | Behaviour | |---|---| | MyApp.app.dSYM | Single dSYM bundle — packed into a zip and uploaded. | | build/dSYMs/ (directory) | All *.dSYM bundles found recursively (max depth 4) are packed together into one zip. | | MyApp.xcarchive | The dSYMs/ subdirectory of the archive is walked; all discovered bundles are packed. | | symbols.zip | Uploaded as-is (assumed to already contain packed dSYM bundles). |

Pack-and-retry behaviour

  • Multiple dSYM bundles are zipped into a single symbols.zip before upload, preserving each bundle's internal directory tree.
  • The upload is retried up to 3 times on transient failures (HTTP 5xx, HTTP 429, network errors), with 500 ms / 1 000 ms / 1 500 ms back-off between attempts.
  • HTTP 4xx errors (auth failure, validation error) are not retried.
  • The temp zip is always cleaned up on exit.

REST endpoint called

POST https://api.newinstance.cloud/api/v1/bugwatch/debug-symbols

Query parameters carry the metadata flags; the body is raw application/octet-stream (the zip). The response body includes { uploadId, status, duplicate? }.


Verifying the upload

After a successful upload the CLI prints the uploadId:

✓ uploaded: ul_abc123 [QUEUED]

You can poll the REST API to confirm indexing is complete:

curl -H "x-api-key: $BUGWATCH_AUTH_TOKEN" \
  "https://api.newinstance.cloud/api/v1/bugwatch/debug-symbols/uploads/ul_abc123"

status transitions: QUEUEDPROCESSINGAVAILABLE (ready to symbolicate) or FAILED.

You can also list recent uploads:

curl -H "x-api-key: $BUGWATCH_AUTH_TOKEN" \
  "https://api.newinstance.cloud/api/v1/bugwatch/debug-symbols/uploads?limit=10&status=AVAILABLE"

Both endpoints require the symbols:read permission scope on the key.


CI integration recipes

Every recipe follows the same four steps:

  1. Build / archive the app so Xcode produces dSYMs (set Debug Information Format = DWARF with dSYM File for the Release config).
  2. Expose BUGWATCH_AUTH_TOKEN as a secret env var in the pipeline.
  3. Run npx @newinstance/bugwatch-cli symbols upload <path> --release <v> --build-number <n>.
  4. Optionally confirm indexing via the REST API or dashboard.

Only the provider-specific wiring differs — see below.

Xcode Run Script build phase

Add a Run Script phase in Xcode (after "Compile Sources"). Set it to run for Release builds only. Xcode provides the dSYM path via a built-in env var.

if [ "$CONFIGURATION" != "Release" ] || [ "$PLATFORM_NAME" = "iphonesimulator" ]; then
  exit 0
fi
[ -z "$BUGWATCH_AUTH_TOKEN" ] && {
  echo "warning: BUGWATCH_AUTH_TOKEN unset — skipping dSYM upload"
  exit 0
}

npx @newinstance/bugwatch-cli symbols upload "$DWARF_DSYM_FOLDER_PATH" \
  --release "$MARKETING_VERSION" \
  --build-number "$CURRENT_PROJECT_VERSION" \
  --bundle-id "$PRODUCT_BUNDLE_IDENTIFIER" \
  --upload-source run-script

Store BUGWATCH_AUTH_TOKEN in Xcode build settings or a non-committed .xcconfig file — not hard-coded in the script.

Local Xcode (manual archive)

To publish dSYMs from a build you archived on your own Mac (Xcode Product → Archive) — handy for a one-off symbolication fix without wiring up CI:

  1. Open Window → Organizer → Archives, right-click your archive → Show in Finder.
  2. Drag the .xcarchive into Terminal to paste its exact path (Release archives contain a dSYMs/ folder; the CLI walks it for you).
export BUGWATCH_AUTH_TOKEN="<keyId>:<secret>"
npx @newinstance/bugwatch-cli symbols upload \
  "~/Library/Developer/Xcode/Archives/2026-06-28/MyApp 2026-06-28 10.30.xcarchive" \
  --release 1.4.2 \
  --build-number 318 \
  --bundle-id com.example.MyApp \
  --upload-source local-xcode

This is the same upload the CI recipes run, just triggered by hand. (You can also point it at the exported dSYMs/ directory or a single MyApp.app.dSYM.)

Fastlane

After build_app / gym, pass the archive path to the CLI:

build_app(scheme: "MyApp", export_method: "app-store")

sh(
  "npx @newinstance/bugwatch-cli symbols upload " \
  "'#{lane_context[SharedValues::XCODEBUILD_ARCHIVE]}' " \
  "--release '#{get_version_number}' " \
  "--build-number '#{get_build_number}' " \
  "--upload-source fastlane"
)

Set BUGWATCH_AUTH_TOKEN in your Fastfile environment, a .env file, or your CI's secret store.

GitHub Actions (macOS runner)

jobs:
  ios-build:
    runs-on: macos-14
    env:
      BUGWATCH_AUTH_TOKEN: ${{ secrets.BUGWATCH_AUTH_TOKEN }}
    steps:
      - uses: actions/checkout@v4

      - name: Select Xcode
        run: sudo xcode-select -s /Applications/Xcode_15.4.app

      - name: Archive
        run: |
          xcodebuild \
            -scheme MyApp \
            -configuration Release \
            -archivePath build/MyApp.xcarchive \
            archive

      - name: Upload dSYMs to BugWatch
        run: |
          npx @newinstance/bugwatch-cli symbols upload build/MyApp.xcarchive \
            --release "$(agvtool mvers -terse1)" \
            --build-number "${{ github.run_number }}" \
            --upload-source ci

Add BUGWATCH_AUTH_TOKEN in Settings → Secrets and variables → Actions.

Xcode Cloud

Add a ci_post_xcodebuild.sh script to the root of your repo. Xcode Cloud sets $CI_ARCHIVE_PATH to the .xcarchive produced by the workflow.

#!/bin/sh
set -e
[ -z "$BUGWATCH_AUTH_TOKEN" ] && exit 0

npx @newinstance/bugwatch-cli symbols upload "$CI_ARCHIVE_PATH" \
  --release "$CI_PRODUCT_VERSION" \
  --build-number "$CI_BUILD_NUMBER" \
  --upload-source xcode-cloud

Set BUGWATCH_AUTH_TOKEN in Xcode Cloud → Workflows → Environment → Environment Variables (mark it Secret).

Bitrise

Add a Script step after the Xcode Archive & Export for iOS step. Bitrise provides $BITRISE_XCARCHIVE_PATH (the archive) and $BITRISE_DSYM_DIR_PATH (extracted dSYMs — either works).

npx @newinstance/bugwatch-cli symbols upload "$BITRISE_XCARCHIVE_PATH" \
  --release "$BITRISE_APP_VERSION" \
  --build-number "$BITRISE_BUILD_NUMBER" \
  --upload-source bitrise

Add BUGWATCH_AUTH_TOKEN as a Secret in Bitrise Secrets.

Codemagic

Add a post-build script in your codemagic.yaml:

scripts:
  - name: Upload dSYMs to BugWatch
    script: |
      npx @newinstance/bugwatch-cli symbols upload "$CM_EXPORT_DIR" \
        --release "$CM_APP_VERSION" \
        --build-number "$CM_BUILD_NUMBER" \
        --upload-source codemagic
    environment:
      BUGWATCH_AUTH_TOKEN: $BUGWATCH_AUTH_TOKEN

Store BUGWATCH_AUTH_TOKEN in Codemagic → Team / App → Environment variables (mark it Secret / Secured).

Other macOS CI (GitLab, CircleCI, Jenkins, generic shell)

The command is the same everywhere. The only differences are how you expose the archive path and secret:

  • GitLab CI (macOS runner): add a job script step; set BUGWATCH_AUTH_TOKEN as a masked CI/CD variable in Settings → CI/CD → Variables.
  • CircleCI (macOS executor): add a run step; store the token in a Context or project environment variable.
  • Jenkins (macOS agent): add a shell build step; bind the token from a Credentials (Secret Text) entry to the BUGWATCH_AUTH_TOKEN env var.
  • Any macOS shell:
    BUGWATCH_AUTH_TOKEN=<keyId>:<secret> \
      npx @newinstance/bugwatch-cli symbols upload <archive> \
      --release 1.4.2 --build-number 318

Exit codes

| Code | Meaning | |---|---| | 0 | Upload accepted by the server. | | 1 | Usage or input error (missing path, no token, unsupported file type). | | 2 | Upload failure (all retries exhausted or server rejected the request). |


Troubleshooting

No dSYM file generated Confirm the scheme's Release configuration has Build Settings → Debug Information Format = DWARF with dSYM File. Simulator builds never produce dSYMs — the guard [ "$PLATFORM_NAME" = "iphonesimulator" ] in the run-script recipe handles this.

UUID mismatch — crash still not symbolicated The dSYM must come from the exact same build that crashed. Re-upload the dSYM from that specific archive. Compare UUIDs with dwarfdump --uuid MyApp.app.dSYM.

Missing framework symbols (React Native / Hermes / Flutter / third-party) Upload the full .xcarchive or the dSYMs/ directory — not just your app's .dSYM. Each bundled framework ships its own dSYM.

Duplicate upload The CLI reports (duplicate of an existing upload) and exits 0. Nothing breaks; the server de-duplicates by UUID.

Archive too large or rejected Confirm the input is a real .dSYM, .xcarchive, directory, or .zip. The server enforces a 2 GB size cap on dSYM uploads.

Authentication failure (HTTP 401) The x-api-key value is wrong, expired, or the key does not have the symbols:upload scope. Regenerate the key in the dashboard and confirm the scope is assigned.

HTTP 429 / rate-limited The CLI retries automatically with back-off. If it still fails, wait a moment and re-run — or contact support.

Apple system framework frames unresolved Expected. Your uploaded dSYMs only contain symbols for your app and bundled frameworks. Apple's private OS symbols are resolved separately (or not at all for private-framework frames).

React Native JS or Flutter Dart frames unresolved Those require source-map or --split-debug-info symbol uploads, which are separate from dSYMs and handled by a different upload flow.


Links

  • BugWatch dashboard: merchant dashboard → your project → Issues / Logs
  • REST API Swagger: https://api.newinstance.cloud/swagger.json
  • Upload status endpoint: GET /api/v1/bugwatch/debug-symbols/uploads/{uploadId}
  • iOS SDK: bug-watch-ios
  • Android SDK: cloud.newinstance:bugwatch on Maven Central
  • JS/TS SDK: @newinstance/bugwatch on npm

Package status

| Field | Value | |---|---| | Package name | @newinstance/bugwatch-cli | | Version | 0.1.0 | | npm published | Yes — 0.1.0 on npm | | Tests | bun test — 17 passing (discovery, upload retry/redaction, CLI validation) | | Platforms supported | dSYM only (ios, macos, tvos, watchos, visionos, catalyst) | | Node requirement | ≥ 18 |