Set up Tailglow with an agent

Set up Tailglow with an agent

This page is written for AI agents such as Claude Code, Codex, Cursor and Cowork that are helping someone set up Tailglow. People are welcome to read it too.

Tailglow turns the data a product sends into live charts and pages. Data arrives at a source and lands in collections. Views reshape it, and metrics count it; charts, pages and monitors are built on metrics. Every project runs on its own server, which Tailglow provisions and operates.

Start by asking

Unless the person has already said, ask what they want to see first. Each answer maps to one path in step 4:

They wantPath
Visitors, page views and clicks in a web appWeb app
Events, jobs or errors from a backendBackend
Screens and errors in a React Native or Expo appReact Native
To know that a site or API is upUptime check
Data they already have: files, exports, another serviceAnything else

1. Sign in

npx @tailglow/cli login

Without a terminal attached, which is how an agent runs it, the command prints a link and a code, remembers the sign-in, and exits. Show both to the person. They sign in, or create an account if they have none (the first 3 days are free and need no card), check that the page shows the same code, and approve. Then finish signing in:

npx @tailglow/cli login --wait

--wait waits up to a minute. Exit code 75 means the person has not approved yet: run it again. Exit code 1 with status unreachable means the API could not be reached: the sign-in is kept, so run login --wait again once the connection is back. Status consumed means the credential was already handed out: start over with login --new. Any other exit code 1 means the sign-in was denied, expired or withdrawn: start over with login.

This signs the CLI in as the person, with what their role allows in each of their teams, starting in the team they choose. To use an API key for one team instead, with only the permissions the person picks, add --method api-key; that team needs a project first.

When Tailglow is at capacity, a brand-new account joins a waitlist instead of signing in, so the sign-in cannot be approved and --wait keeps exiting 75 until it expires. If the person sees the waitlist, say so and stop until they are let in.

The credential is saved to ~/.tailglow/config.json and the CLI uses it from then on. You never need to see it: do not ask for it, print it, or put it in code. tglow logout removes it.

To keep the CLI around, install it once. It needs Node 18.3 or newer:

npm install -g @tailglow/cli
tglow whoami

In CI, set TAILGLOW_API_KEY to an API key instead of logging in.

2. Learn the CLI as you go

Every command has the shape tglow <resource> <command> [flags], and the CLI documents itself:

tglow                                # every resource and the global flags
tglow sources                        # the commands on one resource
tglow sources create --help --json   # one command's flags, types, required fields and rules

Read --help --json before you call a command for the first time. It is generated from the same validation the API enforces, so it is always current, and its notes carry rules a field list cannot.

  • Flags are field names in kebab-case: time_window_minutes is --time-window-minutes.
  • IDs in the path are flags too: --source-id src_x, never a positional argument.
  • Output is JSON whenever it is piped. Read .data, and .pagination.next_cursor to continue a list.
  • Set the project once so you can leave it off every command: tglow config set project prj_...

The CLI also carries these docs, so you do not need to fetch them. tglow docs prints the index and tglow docs guides/sdk prints one page, as markdown even when piped.

3. Pick a project

tglow projects list
tglow projects create --name "Acme web"
tglow config set project prj_...

Reuse a project when the person already has one for this app. A new team’s first project comes with a free trial server, which starts in the background: tglow servers list shows provisioning until it is active.

4. Connect data

Most paths need a source and an ingest key:

tglow sources create --name "Web app"
tglow ingest_keys create --source-id src_...

The ingest key’s url is the address to send records to, with the key already in it. It is null until the project’s server is active; retrieve the key again once it is. An ingest key can only write records into its own source, so it is safe in client-side code. Keep it in the app’s environment configuration anyway, so it can be replaced without a code change.

Web app

npm install @tailglow/browser
import { Tailglow } from "@tailglow/browser";

// The ingest key's url, read from the app's public environment configuration.
const tg = new Tailglow({ url: TAILGLOW_INGEST_URL });

tg.track("signup", { plan: "pro" });
tg.identify("user_123");

Page views, clicks in elements marked data-telemetry, outbound clicks, uncaught errors and performance signals are collected automatically. A site without a build step can use the script tag instead: see Drop-in script.

The SDK ignores localhost by default. To test locally, pass excludeLocalhost: false and tag the traffic, for example context: { environment: "development" }, so it can be filtered out of real charts.

Backend

npm install @tailglow/core
import { TailglowCore } from "@tailglow/core";

const tg = new TailglowCore({ url: process.env.TAILGLOW_INGEST_URL });

tg.track("job_completed", { job_id: "abc" });
await tg.flush();

Nothing is collected automatically on a backend. Flush before the process or request ends. Node 22 or newer, or Bun. Any other language can send records over HTTP.

React Native

Install @tailglow/react-native and follow React Native in the SDK guide. The app passes the SDK its AppState, Platform, storage and navigation, which the guide shows in one file.

Uptime check

A check needs no code. It fetches a public HTTPS address on a schedule and records whether it answered:

tglow checks create --name "Homepage" --source-id src_... --collection-slug uptime --endpoint-url https://acme.com
tglow checks test --check-id chk_...

test fetches once and stores nothing. Checks that share a collection chart together, one row each, which is what a status page is. See Checks.

Anything else

POST JSON, JSONL, CSV, TSV or plain text to the ingest URL. Add &collection=<name> to choose where the records land; the collection is created the first time data arrives for it.

curl -X POST "$TAILGLOW_INGEST_URL&collection=orders" 
  -H "Content-Type: application/json" 
  -d '[{"order_id":"o_1","total":42.5,"created_at":"2026-09-27T12:00:00Z"}]'

202 Accepted means the records are stored and will be processed. Retry on 5xx and on network errors; a 4xx means the request itself has to change. One request can carry up to 20 MiB. See Sending data.

5. Confirm data arrived

tglow collections list --source-id src_...
tglow collections list-docs --collection-id col_...

The browser and backend SDKs write to collections named events, errors and logs. A collection appears with its first record.

6. Build a chart

A view is written for a settled record shape. By default Tailglow settles a shape when it arrives again at least 60 minutes after it was first seen, or when 100 or more records of it arrive in one batch. Check with:

tglow collections list-schemas --collection-id col_...

If the person confirms a candidate shape is real data rather than a one-off test, settle it by hand:

tglow collections update-schema --collection-id col_... --schema-version-id csv_... --state settled

Then create a view on the collection and declare the fields it should produce, based on the records you sampled in step 5. A metric can only use fields the view declares, and its time field has to be one of them, typed date. This example reads the SDK’s events collection:

tglow views create --collection-id col_... --name "Product events" 
  --output-schema '[{"name":"event_time","type":"date"},{"name":"type","type":"string"},{"name":"plan","type":"string"}]'

Field types are string, number, boolean, date, array and null. Tailglow writes the transform that fills those fields from the records. Add --hint only for a rule it cannot read from field names, such as “classify orders above 500 as large”. Choose the fields with care: once the transform is written, the view’s fields cannot be changed in place.

Retrieve the view until its status is active before telling the person the chart is ready. If it is error, read error_message. If waiting_shapes_count is above 0, tglow views list-deferrals --view-id view_... shows what it is waiting on.

tglow views retrieve --view-id view_...

Then build up from the view. The events collection holds page views and clicks as well as your own events, so filter a metric to the event it counts:

tglow metrics create --view-id view_... --name "Signups per day" --timestamp-field event_time 
  --filters '?type=equals:signup' --ui-chart-value count --ui-chart-interval day
tglow pages create --name "Product"
tglow components create --page-id page_... --metric-id mtrc_...

Read --help --json on each command for the rest of its fields.

People who would rather describe a chart in words can ask the assistant in the Tailglow dashboard.

Rules

  • Ask before any delete. Without a terminal attached, delete runs immediately and never asks.
  • Ask before changing servers or billing. Servers cost money.
  • Never print, log or commit the CLI credential. Ingest keys are fine in client-side code.
  • Send only fields that --help --json lists. The API rejects unknown fields.

More