The Analytiics CLI
npx analytiics startThat is setup. It signs you in, creates the project, issues a server write key and writes it to .env, scaffolds analytics.yaml, and installs the instrument agent skill — then tells you the two things it cannot do for you: add the tracker snippet, and ask your agent to instrument the code.
Every step is idempotent, so running it again is a status check rather than a second setup. A project is its site's domain; it is read from homepage in package.json, or you pass it: npx analytiics start example.com.
The individual commands
npx analytiics login # authorize this machine
npx analytiics link example.com # create/attach the project, write a key
npx analytiics init example.com # scaffold analytics.yaml
npx analytiics codegen # write analytics.gen.ts, and push the manifest
npx analytiics push # send analytics.yaml to your dashboard
npx analytiics validate # check the manifest
npx analytiics check # compare the manifest against the code
npx analytiics whoami # who you are signed in as
npx analytiics upgrade maker # open checkout, and wait for the paymentUpgrading without leaving the terminal
npx analytiics upgrade studioIt reads the plan you are on, asks the server for a checkout link, opens it, and then waits — polling until the plan actually changes.
The waiting is the point. This command cannot know whether you paid: it never sees the card, and the page you type it into is Stripe's. What it does instead is keep asking the server, which finds out from Stripe directly. So a Done — you're on Studio is a fact rather than an assumption, and stopping early is not a failure — if you finished paying after it gave up, the plan is live anyway. --no-wait prints the link and exits, for scripts.
An agent can run the whole thing. What it structurally cannot do is finish it: the one irreversible step happens on a page a human is looking at.
Pushing the manifest
Your dashboard draws a card per declared event, ranks its enum properties, and groups events by tag. It can only do that from a manifest it has been given: analytics.yaml lives in your repository and the dashboard renders on ours.
codegen pushes it for you — regenerating the typed SDK is the moment the manifest changed — and --no-push skips that. push does it on its own, for anyone who never runs codegen: a Python or Ruby backend has a tracking plan and no TypeScript to generate.
The file stays the source of truth. Nothing edits it from the dashboard, and what we keep is a copy — to change what your charts show, change the file and push again.
A push that cannot happen never fails codegen. Offline or signed out, it says which manifest your dashboard is still showing and carries on.
Keeping the manifest and the code in step
validate reads the manifest on its own. check reads it against the repository, and is the one to run in CI:
npx analytiics check # warn, and exit 0
npx analytiics check --strict # exit 1 on anything unambiguously wrong
npx analytiics check src apps # only search these pathsIt reports four kinds of drift:
- Sent but not declared. Code emits an event the manifest has never heard of, so nothing derives a chart for it. Add it, or stop sending it.
- Declared but never sent. An event with no call site draws an empty chart, which reads as *nobody did this* rather than *nobody wired this*.
- Properties that diverge. A call passing a property the event does not declare, or omitting a required one.
- A stale `analytics.gen.ts`. The generated module records the manifest it came from, so one built before the last edit is caught even when it still compiles.
Anything ambiguous is reported as nothing at all. A call whose properties are a variable or a spread cannot be read at rest, and a false alarm would cost the credibility of every warning after it — so the check stays quiet rather than guessing. It is a text scan, not a compiler, so it also runs in a repository whose build is broken.
`--strict` never fails on an unused event. Wiring a call site is a decision a person has to make, and an unfinished tracking plan is not a reason to block a release.
A call in a test is a call site like any other, which is usually what you want — an event is declared, and something sends it. Where it isn't, name the paths to search: analytiics check src.
In a pull request
# .github/workflows/analytics.yml
name: analytics
on: pull_request
jobs:
drift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: npx analytiics checkStart there — warnings on every pull request, failing nothing. Once the list is empty, add --strict and it stays empty. No sign-in and no network: the manifest and the code are both in the checkout.
Signing in
Sign-in is the OAuth device flow: the CLI prints a short code and a URL, you approve it in a browser you are already signed into, and the CLI receives a session token. The CLI never sees a password.
The write key is refused rather than written when .env is not covered by .gitignore, because a key committed to a repository is a key you have to rotate.
Agent skills
npx analytiics skills list
npx analytiics skills install instrumentSkills install into .claude/skills/. The instrument skill teaches a coding agent to audit a codebase, propose a tracking plan, and wire up the typed calls — including the parts that are easy to get wrong, like revenue events being server-side only. Skills ship inside the CLI package, so a skill can never disagree with the CLI that generated the code it describes.
Last updated 2026-08-27. This page is also available as Markdown at /docs/cli.md, or from this URL with Accept: text/markdown.