twelvebit
v0.3.3
Published
Set up twelvebit analytics from the terminal: device sign-in, tracking plan (analytics.yaml), validate, browser and server codegen, drift check, link, integrations status, exclusions, agent skills and MCP setup.
Maintainers
Readme
twelvebit CLI
Set up twelvebit analytics from the terminal. No dependencies, Node 18 or later.
npx -y twelvebit init example.cominit prints the approval link and code first and opens the browser. You approve the sign-in code there once: the CLI saves the sign-in on this computer, and later commands reuse it. If init stops before the approval (for example at a coding agent's command timeout), run it again: it continues with the same code and opens no new tab. The CLI writes the site key to .env itself. No key goes through a chat with a coding agent.
Verify the setup on the production domain: deploy, open the site in a normal browser, and run status (or check) until the first event arrives. Local development (localhost, 127.0.0.1) is not tracked, by design.
Commands
| Command | What it does |
|---|---|
| init [domain] [--agent claude\|codex\|cursor\|other] [--no-skills] | Signs in through the browser (device code), finds or creates the site, saves TWELVEBIT_API_KEY in .env (only when git ignores .env), writes analytics.yaml, writes the agent guide (see skills) and prints the script tag. Safe to run again. |
| link [domain] [--scopes ...] | Links the project to a site that already exists. It never creates a site. It signs in (or uses the saved session), saves a new TWELVEBIT_API_KEY in .env with the same rule as init, and adds project: to analytics.yaml when it is missing. When no site matches, it lists your sites and changes nothing. |
| skills [--agent claude\|codex\|cursor\|other] [--force] | Adds or updates a marked twelvebit section in CLAUDE.md and/or AGENTS.md and writes .claude/skills/twelvebit/SKILL.md. Claude Code (--agent claude, or a run inside Claude Code) gets CLAUDE.md; other agents get AGENTS.md. That file is created when it is missing, and the other file gets the same section when it exists. Without an agent: AGENTS.md, or CLAUDE.md when the repo has only that. Other content in those files is kept. A hand-edited SKILL.md is replaced only with --force. |
| validate | Checks analytics.yaml against the full schema, offline. Prints each error with its path. push and codegen run the same check first. |
| codegen [--no-push] [--server] [--server-out <file>] | Writes analytics.gen.ts with typed track functions, then pushes the plan. --server also writes track.server.ts: typed server-side goals, identify() and payment({ amount, currency, transaction_id, plan, renewal }) that post to /api/v1 with TWELVEBIT_API_KEY from the environment. No dependencies; it compiles under tsc --strict. |
| check [--strict] [--offline] [paths...] | Compares the code with the plan: undeclared events, planned events not used, undeclared props, string values outside an enum, missing required props, and a stale analytics.gen.ts. With a site key it also reports the prop problems in the events that the site received in the last 7 days, and the install: the first event from the production domain, or "Waiting for the first event" with a look at the production page (--offline skips this). It warns about data-allow-localhost in the code and a local project:. --strict exits 1 on drift. |
| push | Uploads analytics.yaml. The server validates it again. |
| pull [--force] | Downloads the saved plan. |
| login [--force] | Signs in through the browser and saves the session. |
| logout | Removes the saved session for the app URL and ends it on the server. .env is not changed. |
| whoami [--json] | Shows the signed-in user and the site of the key in .env. Exits 1 when there is neither. |
| status [--json] | Shows what the site received: the first event from the production domain, or "Waiting for the first event from " and what to do. |
| mcp [claude\|codex\|cursor] [--run] | Prints or adds the MCP server for a coding agent. |
| integrations status [provider] [--json] [--strict] | Shows each integration: connected, last sync, last event and last error. It never shows a secret. For an integration that is not connected, it prints the dashboard link where a person connects it. |
| exclusions [list\|add\|remove] [--ips …] [--paths …] [--hostnames …] [--countries …] [--hidden-countries … --yes] [--json] | Shows, adds or removes the IP addresses and ranges, paths, hostnames and countries that are not recorded (comma-separated values). The server checks each entry like Settings → Exclusions, and a repeat changes nothing. --hidden-countries also hides the country's past data in every report, so add needs --yes. Needs a key with write:config to change the lists. |
| billing [status\|checkout\|check-badge] [--json] | status: the account's plan, trial end, events used against the limits, and whether the dashboard asks for a plan (tracking never stops). checkout --plan starter\|growth --tier 10k…10m [--interval month\|year] [--open]: a Dodo Payments checkout link to open in the browser (the payment happens on Dodo's page; owner only; uses the saved sign-in or an admin key). check-badge: the launch offer's backlink check now; exits 1 when the link is not found. |
| open | Opens the dashboard. |
| upgrade [--json] | Shows the latest version on npm and the command that runs it (npx -y twelvebit@latest <command>). It does not install or change anything. |
Options: --url (or TWELVEBIT_URL), --env, --manifest, --out, --server-out, --no-open. The sign-in is saved in ~/.twelvebit/config.json (mode 600), per app URL.
Event and prop names are lowercase snake_case. Two names that give the same camelCase identifier (for example a_1 and a1) are an error, because analytics.gen.ts would not compile.
Release
The CLI is served in two ways. Both use the same source in packages/cli.
Hosted tarball (used by the docs and the setup prompts). From the repo root:
node scripts/pack-cli.mjsThis writes
public/cli/twelvebit-cli.tgzwithDEFAULT_URLset toTWELVEBIT_DEFAULT_URL,NEXT_PUBLIC_APP_URLorhttps://twelvebit.app. Deploy the app to publish it.npm (package name
twelvebit). Bumpversioninpackage.json, check thatDEFAULT_URLinsrc/defaults.mjsishttps://twelvebit.app, then:cd packages/cli npm publish --dry-run # check the file list npm publishprepackwritessrc/tools.gen.mjsfrom the MCP tool registry first, so the agent guidance lists every tool. After the first publish,npx twelvebit@<version> initworks too.After an npm publish, update
CLI_RELEASEinsrc/lib/cli-release.tsin the app (published, andnextPublished: truewhen it wasnext). Until then the hosted docs mark the newer commands "coming in ", because they tell agents to runtwelvebit@latest.
