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

google-apis-cli

v0.1.0

Published

One CLI (gapi) for Google Ads, GTM, GA4 (Admin+Data), Search Console, and Indexing. One login, all scopes, read+write.

Downloads

174

Readme

google-apis-cli (gapi)

gapi is one CLI for Google Ads, GTM, GA4 (Admin + Data), Search Console, and Indexing.

  • One login. One refresh token. All scopes. Read and write.
  • One runtime dependency: google-auth-library (Google). Nothing third-party.
  • All network calls use native fetch.
  • TypeScript 7 (strict), Node 24. Node runs .ts directly (type-stripping) — no build step in dev. Biome for lint + format. pnpm 12 (corepack-pinned) for package management.
  • It replaces the 4 fragmented Google MCPs in vmCODE.

Command shape: gapi <api> <resource> <verb> [--json|--raw]

Install

npm i -g google-apis-cli    # installs the `gapi` bin

Needs Node ≥ 24gapi ships as TypeScript and runs on Node's native type-stripping, so there is no build step and no bundle.

Start here

gapi auth setup   # store your own OAuth Desktop client (id + secret)
gapi auth login   # one consent, all 13 scopes
gapi auth status  # account, refresh token, granted scopes

First run, or a console step fails? docs/SETUP.md walks the five steps and the traps in each. gapi is multi-tenant: every operator brings their own Cloud project.

OAuth App Verification

gapi asks for sensitive scopes (analytics.manage.users, tagmanager.manage.*, adwords, webmasters).

  • Testing mode (default) works for all commands, but the refresh token expires every ~7 days — re-run gapi auth login when it does.
  • Production removes that expiry, but Google requires OAuth App Verification first: a privacy-policy URL, a homepage, and a reviewed consent screen. Review timeline is not guaranteed.

Testing mode is enough to use the CLI; Production is the no-expiry target. Until verification passes, stay in Testing and re-auth on the ~7-day cadence.

Flow

The project has 3 parts. A call moves through them in order.

| Part | File | Function | |---|---|---| | auth | src/auth.ts | gapi auth login gets one OAuth consent. It stores the refresh token in ~/.config/gapi/credentials.json (mode 600). getAccessToken() refreshes the access token. Only part with real handlers. | | manifest | src/apis/*.ts | Each API is data, not code: resource → verb → { httpMethod, pathTemplate, scopes, requiredHeaders?, decoder?, listKey?, query? }. One file per surface. A glob finds them. No central registry. Row/seam types live in src/types.ts. | | executor seam | src/rest.ts | execute(manifestRow, params, { tokenProvider, fetch }) builds the URL, adds headers, follows pagination, applies the decoder, and formats --json/--raw. All network calls pass here. It is the one test seam. |

bin/gapi.ts parses argv. The dispatch, --help, and URL resolution all come from the manifests.

Where to look

| For | Read | |---|---| | Onboarding a Google account: consent, Ads access level, customer IDs, runtime errors | docs/SETUP.md | | What the CLI does, decisions, scopes, endpoints, risks | docs/SPEC.md — behavior source of truth | | How work is tracked (issues, blocking edges) | docs/agents/issue-tracker.md | | Triage labels | docs/agents/triage-labels.md | | Domain vocabulary (CONTEXT.md, ADRs) | docs/agents/domain.md | | Real commands and scripts | package.json, gapi --help |

Add an API or a resource

  • New resource = one manifest row.
  • New API = one new src/apis/<api>.ts file (default-export satisfies Manifest). The glob finds it. No shared file changes.
  • Accept rule — coverage-oracle: the self-check fails if the manifest does not cover 100% of the discovery-doc resources.
  • Test through the executor seam. Inject a fake tokenProvider and fetch. Use no real network.
  • Before commit: pnpm typecheck (tsc --noEmit) · pnpm lint (biome) · pnpm test.
  • Fix lint by fixing the code it flags — never biome --unsafe, never disable a rule to clear it.

Agent skills

| Topic | Rule | Detail | |---|---|---| | Issue tracker | GitHub issues via gh | docs/agents/issue-tracker.md | | Triage labels | 5 canonical labels (string == role) | docs/agents/triage-labels.md | | Domain docs | Single-context (CONTEXT.md + docs/adr/) | docs/agents/domain.md |