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

ecswatch

v0.1.2

Published

Beautiful interactive TUI for inspecting AWS ECS services + a CI-friendly streaming mode for GitHub Actions. Optional LLM-assisted root-cause analysis for failed rollouts.

Readme

ecswatch

build status SemVer Conventional Commits AutoRel

A keen, low-friction watcher for AWS ECS services. CI-friendly streaming for GitHub Actions; full-color interactive TUI when you're at a real terminal; optional LLM-assisted root-cause analysis when something breaks.

  • CI mode (ci.yml friendly): streams ECS events, prints colored rollout progress, exits non-zero on failure, and emits GitHub Actions annotations (::group::, ::error::, ::notice::) so failed deploys surface inline in PR checks.
  • Interactive TUI (default in a real terminal): live deployment panel, task list, recent events, streaming CloudWatch logs, target-group health, and a diagnostics panel with optional LLM root-cause analysis.
  • Snapshot mode (inspect): a single tabular report — kubectl get-style. Health, deployments, tasks, target health, events, logs tail, diagnostics, root cause. Perfect for ecswatch inspect foo on a laptop.
  • Just give it a service name: ecswatch discovers which cluster the service lives in (and caches the map), so you don't have to remember or type cluster names.
  • LLM-assisted root cause (optional): Anthropic + OpenAI fallback chain. If no key is configured, ecswatch degrades to a strong heuristic analyzer — it never hard-fails.

Install

From npm (once published):

npm install -g ecswatch

From a local checkout:

git clone <repo> ecswatch && cd ecswatch
npm install            # runs the build via the `prepare` script
npm link               # exposes `ecswatch` on your PATH

After that, ecswatch --help works from anywhere. If you change the source, run npm run build (or npm run dev for a watcher) — the global bin stays pointed at dist/cli.js.

To uninstall: npm unlink -g ecswatch.

Usage

You give it a service name; ecswatch figures out the cluster.

ecswatch watch    phone-audit              # TUI on a TTY, CI streaming in CI
ecswatch inspect  phone-audit              # one-shot tabular snapshot
ecswatch inspect  phone-audit --logs 80    # also tail 80 log lines
ecswatch ci       phone-audit              # force CI streaming
ecswatch tui      phone-audit              # force interactive TUI
ecswatch watch    phone-audit --once       # snapshot then exit
ecswatch watch    phone-audit --cluster my-cluster   # skip discovery

Cluster discovery & caching

ECS addresses a service as (cluster, service). Rather than make you name the cluster every time, ecswatch discovers it: on first use it scans every cluster in the account/region (ListClustersListServices), builds a service → cluster map, and caches it to ~/.cache/ecswatch/clusters.json (respects XDG_CACHE_HOME). Subsequent calls resolve instantly from the cache.

  • The AWS account comes from your ambient credentials (AWS_PROFILE / SSO / env / IMDS). ecswatch prints the account id + resolved cluster on each run so you can see exactly what you're pointed at.
  • The cache is keyed by accountId:region, so different profiles/regions never collide. Entries expire after 12h; a cache miss for a (possibly new) service also triggers a rescan.
  • Pass --refresh to force a re-scan, or --cluster <name> (or ECS_CLUSTER_NAME) to skip discovery entirely.
  • If a service name exists in multiple clusters, ecswatch errors and asks you to disambiguate with --cluster.

Conventions

| Flag | Default | | -------------- | ------------------------------------------------------------------------ | | --cluster | $ECS_CLUSTER_NAME, else auto-discovered by scanning the account | | --region | $AWS_REGION / $AWS_DEFAULT_REGION or us-east-2 | | --container | $CONTAINER_NAME or app | | --log-group | resolved from the active task definition's awslogs-group if not given | | --refresh | force a cluster re-scan, ignoring the cache |

LLM configuration

Set one or both:

export ANTHROPIC_API_KEY=sk-ant-…
export OPENAI_API_KEY=sk-…

Optionally override the chain (default: anthropic:claude-sonnet-4-6,openai:gpt-5):

export ECSWATCH_LLM_MODELS="anthropic:claude-sonnet-4-6,openai:gpt-5"

If no key is configured, ecswatch uses heuristic diagnostics only — it still tells you about placement failures, image pulls, OOM exits, ALB health-check failures, circuit-breaker rollbacks, and the canonical Manifest does not contain descriptor matching platform 'linux/amd64' architecture mismatch.

TUI keybindings

| Key | Action | | --------- | ----------------------------------------------------------------------- | | 16 | focus deployments · tasks · events · logs · target health · diagnostics | | r | refresh now | | a | run LLM-assisted root-cause analysis | | p | pause / resume log streaming | | ? | toggle help | | q / ^C| quit |

The TUI auto-runs root-cause analysis the first time it sees a FAILED rollout — that's almost always why you opened it.

CI integration

- name: Watch ECS rollout
  env:
    AWS_REGION: us-east-2
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}  # optional
  run: |
    npx ecswatch ci ${{ env.SERVICE_NAME }}

GitHub Actions auto-detection: ecswatch switches into CI mode when CI=true or GITHUB_ACTIONS=true is set, or when stdout is not a TTY. Use --force-tui to override.

CI output is colored via 24-bit ANSI (looks the same in iTerm, Alacritty, and the GitHub Actions web log viewer). Failure summaries are wrapped in ::group:: blocks so they're collapsible in the Actions UI, and ::error:: annotations show up inline on the failed step in the PR view.

What it shows

| Panel | Data | | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Deployments | PRIMARY + ACTIVE deployments, task definition, rollout state, running/desired/pending counts, failed-task counter, rollout reason, age. | | Tasks | Running tasks split by deployment (NEW vs OLD), last status, health, CPU/MB, AZ, uptime. Plus the 3 most recently stopped tasks with stopCode and container exit codes. | | Events | The most recent ECS service events, severity-colored. | | Logs | Live tail of the CloudWatch log group resolved from the task definition. | | Target health | ALB target group health with per-target unhealthy reasons (Target.FailedHealthChecks, Target.Timeout, etc.). | | Diagnostics | Heuristic detections: placement failures, image pull failures, essential container exits, ALB unhealthy, circuit breaker trips, OOM kills, IAM init errors, capacity mismatches. | | Root cause | One- or two-sentence summary + bulleted causes + bulleted fixes. LLM-driven if a key is configured; heuristic fallback otherwise. |

Architecture

bin/ecswatch             ─ shim that loads dist/cli.js (stable for `npm link`)
src/
  cli.ts                 ─ commander-driven CLI, mode dispatcher
  theme.ts               ─ central RGB palette (truecolor; chalk auto-degrades)
  ghAnnotations.ts       ─ GitHub Actions ::group:: / ::error:: / ::notice::
  format/
    table.ts             ─ tiny ANSI-aware table renderer (kubectl-style)
  resolve/
    clusterResolver.ts   ─ service→cluster discovery + on-disk cache
  aws/
    clients.ts           ─ lazy per-region ECS / Logs / ELB / STS clients
    ecs.ts               ─ describe/list services, tasks, task-defs, clusters
    logs.ts              ─ FilterLogEvents + async-iterator tail
    elb.ts               ─ DescribeTargetHealth
    sts.ts               ─ GetCallerIdentity (account id for cache key)
  analyze/
    diagnostics.ts       ─ heuristic failure detectors (events + tasks + targets)
    llm.ts               ─ Anthropic + OpenAI provider chain
    rootCause.ts         ─ compose payload → LLM → parse → fallback heuristic
  modes/
    ci.ts                ─ streaming watcher (CI / non-TTY)
    snapshot.ts          ─ tabular one-shot report
    tui.tsx              ─ Ink renderer
  ui/                    ─ Ink components + hooks (App, panels, theme, hooks)

Dev

npm run typecheck     # tsc --noEmit
npm run build         # esbuild → dist/cli.js (ESM bundle, deps external)
npm run dev           # rebuild on change
npm run validate      # typecheck + build

Publishing

This package targets the public npm registry (unscoped name). When ready:

npm login
npm run validate          # also runs as prepublishOnly
npm publish               # public access is the default for unscoped names

License

MIT