Atune Docs
Get started

Install with an AI coding agent

Paste one prompt into Cursor, Claude Code, Lovable or bolt.new and let the agent wire Atune into your app.

If you build with an AI coding agent, let it do the install. The prompt below is the same one Atune shows under Install in the app. It tells the agent to look at your project first, pick one path (Next.js middleware, track() on another Node backend, or the HTTP API), and verify that events arrive.

Agents can also fetch it directly from useatune.com/install.md.

The prompt has no API key

The agent will ask you for ATUNE_API_KEY. Set it yourself in .env.local or your host's environment from Settings → API key. Don't paste the key into the AI chat: anything you paste there is stored by the AI provider.

The prompt

Install prompt
# Install Atune**IMPORTANT: follow these steps in order. Do not skip step 5 (verification).**## What this doesSends an event to Atune whenever a customer account uses this app, without reading request bodies and without waiting for a response. Atune builds its understanding of the customers from these events. This is the same setup as the docs (https://useatune.com/docs). If you find other Atune instructions that say otherwise, this one wins.## 1. Look at the project firstFind out which language and framework the server uses, which auth system the app has, and what the "account" is: the customer you would bill as one unit (team, organization or company; for B2C apps, the user). Then pick **one** path in step 4:- **A. Next.js 14 or later** → 4A, middleware. Captures every signed-in request automatically.- **B. Another Node.js backend** (Express, Hono, Fastify, Remix, NestJS, jobs and queues) → 4B, `track()`.- **C. Not JavaScript** (Python, Ruby, Go, PHP, Java, ...) → 4C, the HTTP API.Tell the developer which path you picked and why. Do not rewrite auth or routing to make Atune fit.## 2. Install the package (paths A and B)Use the project's package manager: `npm install atune`, `pnpm add atune` or `yarn add atune`. Do not copy SDK code into the project. Path C skips this step.## 3. Set environment variables (all paths)Add to `.env.local` or equivalent (and to your hosting platform's environment variables):```ATUNE_API_KEY=<YOUR_API_KEY>ATUNE_URL=https://useatune.com````ATUNE_URL` is the bare host, with no path. The SDK adds `/api/v1/...` itself. Do not append `/api/v1/events` or any other path.**Do not ask for the API key and do not paste it into this chat.** The developer sets the real value themselves (it is in Atune's Settings). If the placeholder is still there, leave it and tell the developer. Never commit the key.## 4A. Next.js: middlewareUse `proxy.ts` on Next.js 16 and `middleware.ts` on Next.js 14/15, in the same folder as `app/` or `src/app/`. If neither exists, create it:```ts// proxy.ts on Next.js 16; middleware.ts on Next.js 14/15import { createAtuneMiddleware } from "atune";const atune = createAtuneMiddleware();export default function capture(request: Request) {  return atune(request);}```**If a middleware/proxy already exists, do not replace it.** Keep its auth and redirects and call `atune(request)` inside it. If it builds its own response, return `atune(request, response)`. Example with Clerk:```tsimport { clerkMiddleware } from "@clerk/nextjs/server";import { NextResponse } from "next/server";import { clerkAccount, createAtuneMiddleware } from "atune";const atune = createAtuneMiddleware();export default clerkMiddleware(async (auth, request) => {  await auth.protect(); // Keep your app's existing auth policy.  return atune(request, NextResponse.next(), { account: clerkAccount(auth) });});```**Clerk: pass the account from the callback's `auth`, as in the example above** (`clerkAccount(auth)`, `atune` 0.1.5 or later). Without it Atune sends no events, because Clerk's session can't be read inside a proxy any other way. **Supabase and NextAuth** are detected automatically. If the app has teams or organizations, it uses the team/org; otherwise the signed-in user. **Another auth system?** Pass `getAccount` and return the account from a verified server session:```tsimport { createAtuneMiddleware } from "atune";const atune = createAtuneMiddleware({  // Return the customer account (team, org or company) from your verified  // server session. Never trust an account id the client sends.  getAccount: async (request) => {    const session = await getYourSession(request);    return session ? { accountId: session.orgId, userId: session.userId } : null;  },});```## 4B. Another Node.js backend: `track()`Pick 3–5 places where a customer account does something meaningful: creates a resource, completes a core action, invites a teammate. **NOT** every route, **NOT** health checks. Call `track()` where the code already knows the account and the user:```tsimport { track } from "atune";// Where your code already knows the customer account (team, org or company)// and the signed-in user. Don't await it: tracking never delays the response.void track("feature.report.generated", {  accountId: session.orgId,  userId: session.userId,  properties: { reportType: "activation" },});```Use short, stable event names like `feature.report.generated`. `track()` never throws and gives up after one second.## 4C. Other languages: the HTTP APISend one POST from the server for each meaningful action (the same 3–5 places as in 4B). Use a short timeout (about one second), do not wait for the response before answering the user, and never let a failure reach the user:```httpPOST https://useatune.com/api/v1/eventsAuthorization: Bearer <YOUR_API_KEY>Content-Type: application/json{  "accountId": "acme",  "userId": "user_123",  "event": "feature.report.generated",  "properties": { "reportType": "activation" }}```Read the key and host from `ATUNE_API_KEY` and `ATUNE_URL`.## The account (all paths)`accountId` is the customer you bill, not just the signed-in user. Take it from a verified server session, never from a value the client sends. Without an account, no event is sent.## 5. VerifySign in to the app and trigger one of the actions you wired (path A: open a page or call an API route). Then open the event log in Atune (Settings → Event log, https://useatune.com/settings/events). The newest event must have the right name (path A: `http.<method>.<route>`) and the account and user you just used.The SDK logs nothing. If nothing shows up, check these in order:1. `ATUNE_API_KEY` is still the placeholder, or wrong.2. `ATUNE_URL` is not the bare host.3. No account was resolved for the request.

After the agent is done

Check the result like any other install: trigger a real action in your app, then open Settings → Event log in Atune and confirm that the newest event carries the right account and user. See Quickstart for what a correct install writes.

Give the agent customer understanding too

Once events arrive, your agent can ask Atune about your customers over MCP. See Query from an AI agent (MCP).

A complete example to copy from

atune-nextjs-example is a public Next.js 16 + Clerk Organizations app with Atune fully wired in. Its AGENTS.md tells a coding agent where each piece lives and which rules to keep.

On this page