> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trygravity.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Terminal / CLI SDK

> Integrate Gravity ads and tracking into Node.js, Bun, and Deno terminal applications using @gravity-ai/api.

## Installation

```bash theme={null}
npm install @gravity-ai/api
```

Set `GRAVITY_API_KEY` in your server environment.

## How the pieces fit together

<Steps>
  <Step title="Initialize the pixel">
    `gravityPixel()` handles session and visitor tracking automatically. Initialize it once when your app starts.
  </Step>

  <Step title="Prepare context">
    `gravityContext()` captures device signals and session info. Pass the pixel's visitor and session IDs to link tracking with ad requests.
  </Step>

  <Step title="Fetch ads">
    `gravity.getAds(req, messages, placements)` reads the context, adds the client IP, and returns matched ads. Runs in parallel with your LLM call.
  </Step>
</Steps>

## Initialize the pixel

```ts theme={null}
import { gravityPixel } from '@gravity-ai/api';

const pixel = gravityPixel({ pixelId: 'YOUR_PIXEL_ID' });
await pixel.start();
```

Find `YOUR_PIXEL_ID` in your dashboard under **Settings → Platform Settings**.

The pixel automatically manages sessions, visitor IDs, and attribution — same as the browser pixel (`gr-pix.js`), but using local file storage instead of cookies. Session state is persisted and cleaned up automatically on process exit.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `pixelId` | `string` | — | **Required.** Your Gravity pixel ID. |
| `appName` | `string` | `'terminal'` | Application label, used as page title in events. |
| `eventEndpoint` | `string` | `'https://api.trygravity.ai/track/gr-events'` | Event endpoint URL. |
| `sessionEndpoint` | `string` | `'https://api.trygravity.ai/track/gr-session'` | Session endpoint URL. |
| `sessionTimeoutMinutes` | `number` | `30` | Session idle timeout in minutes. |
| `attrMaxAgeDays` | `number` | `180` | Max age for persisted attribution in days. |
| `sessionMaxPages` | `number` | `50` | Max entries in invocation history. |
| `hashIdentityFields` | `boolean` | `true` | Hash identity fields with SHA-256 before sending. |
| `storageDir` | `string` | `'~/.gravity'` | Custom storage directory for session and attribution data. |

## Prepare context

```ts theme={null}
import { gravityContext } from '@gravity-ai/api';

const gravity_context = gravityContext({
  sessionId: pixel.getSessionId()!,
  user: {
    userId: currentUser.id,
    gruid: pixel.getVisitorId(),
    grclid: pixel.getClickId(),
    graid: pixel.getGraid(),
  },
});
```

`gravityContext()` auto-detects terminal device signals (OS, timezone, locale). Required parameters:

| Parameter | Type | Required | Description |
| - | - | - | - |
| `sessionId` | `string` | Yes | From `pixel.getSessionId()` |
| `user.userId` | `string` | **Yes** | Stable per-user identifier |

## Fetch ads

```ts theme={null}
import { Gravity } from '@gravity-ai/api';

const gravity = new Gravity({ production: true });

const { ads } = await gravity.getAds(
  { body: { gravity_context }, headers: {} },
  messages,
  [{ placement: 'inline_response', placement_id: 'main' }],
);
```

<Warning>
  `gravity.getAds()` never throws. On any failure, it returns `{ ads: [] }` silently. Safe to fire-and-forget.
</Warning>

## Full example

```ts theme={null}
import { gravityPixel, gravityContext, Gravity } from '@gravity-ai/api';

// 1. Initialize pixel
const pixel = gravityPixel({ pixelId: 'YOUR_PIXEL_ID' });
await pixel.start();

// 2. Set up ad client
const gravity = new Gravity({ production: true });

// 3. On each user interaction
async function handleQuery(userId: string, messages: any[]) {
  const ctx = gravityContext({
    sessionId: pixel.getSessionId()!,
    user: {
      userId,
      gruid: pixel.getVisitorId(),
      grclid: pixel.getClickId(),
    },
  });

  const { ads } = await gravity.getAds(
    { body: { gravity_context: ctx }, headers: {} },
    messages,
    [{ placement: 'inline_response', placement_id: 'main' }],
  );

  return ads;
}
```

## FAQ

<AccordionGroup>
  <Accordion title="Do I need a separate package?">
    No. `gravityPixel` ships inside `@gravity-ai/api`. Just `npm install @gravity-ai/api` and import it.
  </Accordion>

  <Accordion title="Does this work in Bun and Deno?">
    Yes. It uses standard APIs and falls back gracefully when Node-specific modules aren't available.
  </Accordion>

  <Accordion title="Does the ad request block my LLM response?">
    No. Fire `gravity.getAds()` in parallel with your LLM call. It never throws, so failures are silent.
  </Accordion>

  <Accordion title="Where does the API key go?">
    Set `GRAVITY_API_KEY` as an environment variable. The `Gravity` class reads it automatically. You can also pass it via `new Gravity({ apiKey: '...' })`.
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.