Full-featured CLI for Google Analytics 4 — Data API + Admin API. Reports, realtime, funnels,
cohorts, audience exports, property management, streams, custom dimensions/metrics, key events,
audiences, integrations (Firebase, Google Ads, BigQuery). Also ships an
MCP server so any LLM client (Claude Desktop, Cursor, Cline, Zed)
can call it as a tool, plus an interactive explore REPL for browsing
metric/dimension catalogs.
AI assistant integration. gacli ships native skill packages for Claude Code, Codex, Qwen Code, and Gemini CLI. After install, deploy with one command — your agent becomes an expert gacli operator immediately:
gacli skills install --agent claude --scope user
# or: --agent codex / qwen / gemini / allFull guide: extensions/README.md.
Install from npm:
npm install -g @nalyk/gacliVerify the install was built from this exact GitHub repo at the published commit (via npm provenance / Sigstore attestation):
npm audit signaturesOr build from source:
pnpm install && pnpm build && pnpm link --globalRequires Node.js >= 22.
# See what's installed and what's available
npm view @nalyk/gacli version # latest published version
gacli --version # your current version
# Upgrade in place (most users)
npm install -g @nalyk/gacli@latest
# Pin to a specific version
npm install -g @nalyk/gacli@1.2.3 # adjust to taste
# Pre-release channel (semantic-release publishes here from the `next` branch)
npm install -g @nalyk/gacli@next
# Verify the new install is signed by the GitHub repo
npm audit signaturesAfter upgrading, re-run gacli skills install --agent <agent> so any new
or updated skill content lands in your AI CLI's skill directory. The skill
files are versioned with gacli — installing a fresh gacli does NOT
auto-refresh already-deployed skills. Pass --force to overwrite without
prompting:
gacli skills install --agent all --forcegacli supports two authentication methods: OAuth 2.0 (interactive) and service account (JSON key file).
- Create a Desktop OAuth client in Google Cloud Console
- Download the
client_secret_*.jsonfile - Run:
gacli auth login --client-secret-file ./client_secret.jsonThis opens a browser-based consent flow and saves tokens to ~/.gacli/oauth-tokens.json.
To save the client secret path for future use:
gacli config set oauthClientSecretFile /path/to/client_secret.json
gacli auth loginSet credentials via one of:
GOOGLE_APPLICATION_CREDENTIALSenvironment variablegacli config set credentials /path/to/service-account.json
OAuth tokens (if present) > service account file > environment variable.
gacli auth status # Show active auth method
gacli auth logout # Remove saved OAuth tokens
gacli auth logout --revoke # Revoke token at Google, then removeScopes: analytics.readonly, analytics.edit.
| Flag | Description |
|---|---|
-p, --property <id> |
GA4 property ID (overrides config/env) |
-f, --format <fmt> |
table (default), json, ndjson, csv, chart |
-o, --output <file> |
Write output to file |
--no-color |
Disable colors |
-v, --verbose |
Verbose logging |
Property ID resolution: --property > config.property > GA4_PROPERTY_ID env var.
# Set default property
gacli config set property 371981488
# Simple report — activeUsers by day, last 7 days
gacli report run -m activeUsers -d date
# Same report as JSON
gacli report run -m activeUsers -d date -f json
# NDJSON — one row per line, ideal for jq pipelines
gacli report run -m sessions -d country -f ndjson | jq 'select(.sessions | tonumber > 100)'
# CSV for spreadsheets
gacli report run -m sessions -d country -f csv -o report.csv
# ASCII chart in terminal
gacli report run -m sessions -d date --start-date 30daysAgo -f chart
# Realtime
gacli report realtime -m activeUsers -d country
# List accounts
gacli admin accounts list
# List properties
gacli admin properties list --account 232284173
# Metadata — search dimensions
gacli metadata get --type dims --search "page"
# Dimension/metric compatibility check
gacli metadata check-compatibility -m sessions -m totalUsers -d country -d deviceCategory
# Top 10 pages by sessions
gacli report run -m sessions -d pagePath --order-by "metric:sessions:desc" --limit 10
# Custom dimensions
gacli admin custom-dimensions list
# Audience export, blocking until done
gacli audience export create --audience properties/371981488/audiences/12345 --watch
# Browse the metric/dimension catalog interactively
gacli explore
# Run as an MCP server (stdio) — see MCP.md
gacli mcp serve
# Current config
gacli config listgacli
auth login|logout|status
report run|batch|pivot|batch-pivot|realtime|funnel|cohort
metadata get|check-compatibility
audience export create|get|list|query
audience recurring create|get|list
admin accounts list
admin properties list|get|create|update|delete
admin datastreams list|get|create|update|delete
admin custom-dimensions list|get|create|update|archive
admin custom-metrics list|get|create|update|archive
admin key-events list|get|create|update|delete
admin audiences list|get|create|update|archive
admin access-bindings list|get|create|update|delete
admin firebase-links list|get|create|delete
admin google-ads-links list|get|create|update|delete
admin bigquery-links list|get|create|delete
config set|get|list
explore
mcp serve
| Format | Usage |
|---|---|
table |
Colored ASCII table (default) |
json |
{rowCount, data:[{...}]} shape — pipe to jq |
ndjson |
One JSON object per line, newline-separated — clean piping into jq -c, ClickHouse, BigQuery loads |
csv |
Properly escaped CSV, import into spreadsheets |
chart |
ASCII bar chart in terminal |
Shorthand: field==value, field!=value, field=~regex, field>100, field>=100, field<100, field<=100.
gacli report run -m sessions -d country --dimension-filter "country==US"
gacli report run -m sessions -d pagePath --dimension-filter "pagePath=~/blog/"
gacli report run -m sessions -d date --metric-filter "sessions>100"Multiple filters are combined with AND.
Stored in ~/.gacli/config.json.
| Key | Description |
|---|---|
credentials |
Path to service account JSON file |
property |
Default GA4 property ID |
format |
Default output format |
noColor |
Disable colors (true/false) |
verbose |
Verbose logging (true/false) |
oauthClientSecretFile |
Path to OAuth client secret JSON file |
| Variable | Default | Effect |
|---|---|---|
GA4_PROPERTY_ID |
— | Default property when neither --property nor config.property is set |
GOOGLE_APPLICATION_CREDENTIALS |
— | Path to service-account JSON; lowest-priority auth source |
GACLI_VERBOSE |
0 |
When 1, error stack traces are printed alongside the human-readable error |
GACLI_MAX_RETRIES |
3 |
Max retries on retriable gRPC errors (codes 8 quota, 14 unavailable). Other errors never retry |
GACLI_RETRY_BASE_MS |
500 |
Base delay for exponential-backoff-with-jitter; capped at base * 2^attempt |
gacli mcp serveStarts a stdio MCP server exposing four read-only tools — gacli_report_run,
gacli_report_realtime, gacli_metadata, gacli_check_compatibility — to any MCP client. The
server reuses gacli's existing auth chain, retry policy, and property resolution.
Wire-up examples for Claude Desktop, Cursor, Cline, and Zed are in MCP.md, including how to pin different properties per client via the env block.
gacli exploreLoads the property's metric and dimension catalog and drops into a REPL with list, search,
show <apiName>, custom, and help commands. Tab-completion is available on show <apiName>.
Useful when you don't remember field names.
pnpm install
pnpm verify # lint + type-check + test + skill-lint + build
pnpm test:watch # vitest watch mode
pnpm dev <args> # run from source (no build step)Lint/format is Biome, tests are Vitest. The CI
workflow runs pnpm verify on Node 22 and Node 24 for every push and PR.
Releases are fully automated by semantic-release
on every push to main. There is no manual tag, no manual npm publish, no
manual version bump anywhere — package.json, CHANGELOG.md, the git tag,
the npm publish, and the GitHub Release all fall out of one workflow run.
Commit message → release type (Conventional Commits):
| Commit prefix | Release |
|---|---|
feat: … |
minor (1.1.0 → 1.2.0) |
fix: …, perf: …, refactor: … |
patch (1.1.0 → 1.1.1) |
docs(readme): … |
patch |
chore:, docs:, test:, ci:, build:, style: |
no release |
Any commit with BREAKING CHANGE: in the body |
major (1.1.0 → 2.0.0) |
The flow:
- You push a
feat:orfix:commit tomain. .github/workflows/release.ymlruns the full verify gate.- It packs the tarball and smoke-tests
npm install -g <tarball>locally. - It runs
semantic-releasewhich:- Determines next semver from commits since the last tag.
- Bumps
package.jsonand prependsCHANGELOG.md. - Commits both back to
mainaschore(release): vX.Y.Z [skip ci]. - Tags
vX.Y.Zand pushes. - Publishes to npm via OIDC trusted publishing (no
NPM_TOKEN). - Creates the GitHub Release with auto-generated notes + the
.tgzasset.
- It smoke-tests the live npm version end-to-end.
The [skip ci] marker on the release commit prevents the workflow from
re-triggering itself; the workflow also short-circuits on any commit whose
message starts with chore(release):.
Pre-release channels: push to a next or beta branch instead of main
to publish to the corresponding npm dist-tag (@nalyk/gacli@next).
Branch protection requirement. semantic-release pushes the bump commit
back to main. Configure the main branch protection rule (Settings →
Branches → main) to allow GitHub Actions / repository administrators to
bypass required PRs and required status checks. Without that, the
@semantic-release/git step fails with HTTP 403.
| File | Purpose |
|---|---|
README.md |
This file — user setup and quick reference |
help.md |
Verbose human-readable command reference (every flag, every example) |
MCP.md |
MCP server setup for Claude Desktop, Cursor, Cline, Zed |
PUBLISHING.md |
npm release process — OIDC trusted publishing, bootstrap, ongoing flow |
DISTRIBUTION.md |
Single-binary (Node SEA) build notes; multi-platform release tradeoffs |
CONTRIBUTING.md |
How to contribute, the verify gate, architectural rules |
SECURITY.md |
Security policy, vulnerability disclosure, hardening notes |
LICENSE |
MIT |
CLAUDE.md |
Conventions Claude follows when working in this repo |
Node 22+, ESM-only TypeScript 6, Commander 14, @google-analytics/data v5 + /admin v9,
google-auth-library v9, @modelcontextprotocol/sdk 1.x, zod, ora, chalk, cli-table3, boxen.
Dev: Vitest, Biome, tsx.