Analytics
Usage rollups: global and daily totals, per-session detail, the session list that backs the project breakdown, the leaderboard, and the combined data payload.
Send these requests to your own running server. Values stay in this browser.
How this works
Start a server with nikcli serve --hostname 127.0.0.1 --port 4096. Requests go
straight from this page to that address — the browser allows it because loopback counts as a
secure origin, and the server allows it because nikcli-ai.dev is in its CORS
allowlist.
To try things without touching your real sessions or config, start the server with
NIKCLI_TEST_HOME pointed at a throwaway directory — see
the guided tour.
Operations
6 endpoints, generated from the
server's own OpenAPI document. Every path also accepts the
directory and workspace query parameters that select which instance
handles the request.
| get | /analytics/global | analytics.global |
| get | /analytics/daily | analytics.daily |
| get | /analytics/session/{sessionID} | analytics.session |
| get | /analytics/sessions | analytics.sessions |
| get | /analytics/leaderboard | analytics.leaderboard |
| get | /analytics/data | analytics.data |
analytics.global | Name | In | Type | Required |
|---|---|---|---|
| directory | query | string | optional |
| workspace | query | string | optional |
{ version: 1 updatedAt: | number | "Infinity" | "-Infinity" | "NaN" totals: { sessions: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: AnalyticsTokenBreakdown cost: | number | "Infinity" | "-Infinity" | "NaN" toolCalls: | number | "Infinity" | "-Infinity" | "NaN" } byProvider: { [key: string]: AnalyticsProviderStat } byModel: { [key: string]: AnalyticsModelStat } byProject: { [key: string]: AnalyticsProjectStat } }
Example response from schema
{
"version": 1,
"updatedAt": 0,
"totals": {
"sessions": 0,
"messages": 0,
"tokens": {
"input": 0,
"output": 0,
"reasoning": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"cost": 0,
"toolCalls": 0
},
"byProvider": {},
"byModel": {},
"byProject": {}
} Generated from the response schema — field values are placeholders, the shape is real.
SDK example
import { createNikcliClient } from "@nikcli-ai/sdk/httpapi"
const client = createNikcliClient()
await client.analytics.global({
...
}) Try it
analytics.daily | Name | In | Type | Required |
|---|---|---|---|
| from | query | string | null | optional |
| to | query | string | null | optional |
| days | query | string | null | optional |
| directory | query | string | optional |
| workspace | query | string | optional |
({ date: string sessions: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: AnalyticsTokenBreakdown cost: | number | "Infinity" | "-Infinity" | "NaN" toolCalls: | number | "Infinity" | "-Infinity" | "NaN" tools: { [key: string]: { calls: | number | "Infinity" | "-Infinity" | "NaN" success: | number | "Infinity" | "-Infinity" | "NaN" error: | number | "Infinity" | "-Infinity" | "NaN" } } providers: { [key: string]: { messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: | number | "Infinity" | "-Infinity" | "NaN" cost: | number | "Infinity" | "-Infinity" | "NaN" } } models: { [key: string]: { messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: | number | "Infinity" | "-Infinity" | "NaN" cost: | number | "Infinity" | "-Infinity" | "NaN" } } recordedAt: | number | "Infinity" | "-Infinity" | "NaN" })[]
Example response from schema
[
{
"date": "",
"sessions": 0,
"messages": 0,
"tokens": {
"input": 0,
"output": 0,
"reasoning": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"cost": 0,
"toolCalls": 0,
"tools": {},
"providers": {},
"models": {},
"recordedAt": 0
}
] Generated from the response schema — field values are placeholders, the shape is real.
SDK example
import { createNikcliClient } from "@nikcli-ai/sdk/httpapi"
const client = createNikcliClient()
await client.analytics.daily({
...
}) Try it
analytics.session | Name | In | Type | Required |
|---|---|---|---|
| sessionID | path | string | required |
| directory | query | string | optional |
| workspace | query | string | optional |
{ sessionID: string projectID: string directory: string title: string providerID: string modelID: string messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: AnalyticsTokenBreakdown cost: | number | "Infinity" | "-Infinity" | "NaN" toolCalls: | number | "Infinity" | "-Infinity" | "NaN" duration: | number | "Infinity" | "-Infinity" | "NaN" time: { created: | number | "Infinity" | "-Infinity" | "NaN" completed: | number | "Infinity" | "-Infinity" | "NaN" } }
{ error: "Session not found" }
Example response from schema
{
"sessionID": "",
"projectID": "",
"directory": "",
"title": "",
"providerID": "",
"modelID": "",
"messages": 0,
"tokens": {
"input": 0,
"output": 0,
"reasoning": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"cost": 0,
"toolCalls": 0,
"duration": 0,
"time": {
"created": 0,
"completed": 0
}
} Generated from the response schema — field values are placeholders, the shape is real.
SDK example
import { createNikcliClient } from "@nikcli-ai/sdk/httpapi"
const client = createNikcliClient()
await client.analytics.session({
...
}) Try it
analytics.sessions | Name | In | Type | Required |
|---|---|---|---|
| directory | query | string | optional |
| workspace | query | string | optional |
({ sessionID: string projectID: string directory: string title: string providerID: string modelID: string messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: AnalyticsTokenBreakdown cost: | number | "Infinity" | "-Infinity" | "NaN" toolCalls: | number | "Infinity" | "-Infinity" | "NaN" duration: | number | "Infinity" | "-Infinity" | "NaN" time: { created: | number | "Infinity" | "-Infinity" | "NaN" completed: | number | "Infinity" | "-Infinity" | "NaN" } })[]
Example response from schema
[
{
"sessionID": "",
"projectID": "",
"directory": "",
"title": "",
"providerID": "",
"modelID": "",
"messages": 0,
"tokens": {
"input": 0,
"output": 0,
"reasoning": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"cost": 0,
"toolCalls": 0,
"duration": 0,
"time": {
"created": 0,
"completed": 0
}
}
] Generated from the response schema — field values are placeholders, the shape is real.
SDK example
import { createNikcliClient } from "@nikcli-ai/sdk/httpapi"
const client = createNikcliClient()
await client.analytics.sessions({
...
}) Try it
analytics.leaderboard | Name | In | Type | Required |
|---|---|---|---|
| directory | query | string | optional |
| workspace | query | string | optional |
{ models: ({ key: string providerID: string modelID: string sessions: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: AnalyticsModelTokens cost: | number | "Infinity" | "-Infinity" | "NaN" firstUsed: | number | "Infinity" | "-Infinity" | "NaN" lastUsed: | number | "Infinity" | "-Infinity" | "NaN" totalTokens: | number | "Infinity" | "-Infinity" | "NaN" })[] providers: ({ id: string sessions: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: | number | "Infinity" | "-Infinity" | "NaN" cost: | number | "Infinity" | "-Infinity" | "NaN" })[] projects: ({ id: string sessions: | number | "Infinity" | "-Infinity" | "NaN" tokens: | number | "Infinity" | "-Infinity" | "NaN" cost: | number | "Infinity" | "-Infinity" | "NaN" lastActive: | number | "Infinity" | "-Infinity" | "NaN" })[] }
Example response from schema
{
"models": [
{
"key": "",
"providerID": "",
"modelID": "",
"sessions": 0,
"messages": 0,
"tokens": {
"input": null,
"output": null,
"reasoning": null
},
"cost": 0,
"firstUsed": 0,
"lastUsed": 0,
"totalTokens": 0
}
],
"providers": [
{
"id": "",
"sessions": 0,
"messages": 0,
"tokens": 0,
"cost": 0
}
],
"projects": [
{
"id": "",
"sessions": 0,
"tokens": 0,
"cost": 0,
"lastActive": 0
}
]
} Generated from the response schema — field values are placeholders, the shape is real.
SDK example
import { createNikcliClient } from "@nikcli-ai/sdk/httpapi"
const client = createNikcliClient()
await client.analytics.leaderboard({
...
}) Try it
analytics.data | Name | In | Type | Required |
|---|---|---|---|
| days | query | string | null | optional |
| seriesDays | query | string | null | optional |
| directory | query | string | optional |
| workspace | query | string | optional |
| { totals: { tokens: | number | "Infinity" | "-Infinity" | "NaN" inputTokens: | number | "Infinity" | "-Infinity" | "NaN" outputTokens: | number | "Infinity" | "-Infinity" | "NaN" cacheReadTokens: | number | "Infinity" | "-Infinity" | "NaN" sessions: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" toolCalls: | number | "Infinity" | "-Infinity" | "NaN" costUsd: | number | "Infinity" | "-Infinity" | "NaN" models: | number | "Infinity" | "-Infinity" | "NaN" providers: | number | "Infinity" | "-Infinity" | "NaN" authors: | number | "Infinity" | "-Infinity" | "NaN" pricePerMillion: | number | "Infinity" | "-Infinity" | "NaN" costPerSession: | number | "Infinity" | "-Infinity" | "NaN" tokensPerSession: | number | "Infinity" | "-Infinity" | "NaN" cacheRatio: | | number | "Infinity" | "-Infinity" | "NaN" | null change: | | number | "Infinity" | "-Infinity" | "NaN" | null } models: AnalyticsDataModelStat[] authors: ({ author: string tokens: | number | "Infinity" | "-Infinity" | "NaN" sessions: | number | "Infinity" | "-Infinity" | "NaN" share: | number | "Infinity" | "-Infinity" | "NaN" models: | number | "Infinity" | "-Infinity" | "NaN" })[] series: ({ day: string byModel: { [key: string]: | number | "Infinity" | "-Infinity" | "NaN" } tokens: | number | "Infinity" | "-Infinity" | "NaN" sessions: | number | "Infinity" | "-Infinity" | "NaN" })[] months: AnalyticsDataPeriodStat[] lifetime: AnalyticsDataPeriodStat seriesModels: string[] windowDays: | number | "Infinity" | "-Infinity" | "NaN" seriesDays: | number | "Infinity" | "-Infinity" | "NaN" from: string to: string generatedAt: | number | "Infinity" | "-Infinity" | "NaN" } | null
Example response from schema
{
"totals": {
"tokens": 0,
"inputTokens": 0,
"outputTokens": 0,
"cacheReadTokens": 0,
"sessions": 0,
"messages": 0,
"toolCalls": 0,
"costUsd": 0,
"models": 0,
"providers": 0,
"authors": 0,
"pricePerMillion": 0,
"costPerSession": 0,
"tokensPerSession": 0,
"cacheRatio": 0,
"change": 0
},
"models": [
{
"model": "",
"provider": "",
"author": "",
"tokens": 0,
"inputTokens": 0,
"outputTokens": 0,
"reasoningTokens": 0,
"cacheReadTokens": 0,
"cacheWriteTokens": 0,
"sessions": 0,
"messages": 0,
"toolCalls": 0,
"costUsd": 0,
"share": 0,
"pricePerMillion": 0,
"costPerSession": 0,
"tokensPerSession": 0,
"cacheRatio": 0
}
],
"authors": [
{
"author": "",
"tokens": 0,
"sessions": 0,
"share": 0,
"models": 0
}
],
"series": [
{
"day": "",
"byModel": {},
"tokens": 0,
"sessions": 0
}
],
"months": [
{
"month": "",
"tokens": 0,
"inputTokens": 0,
"outputTokens": 0,
"cacheReadTokens": 0,
"messages": 0,
"toolCalls": 0,
"sessions": 0,
"costUsd": 0,
"models": 0,
"pricePerMillion": 0,
"costPerSession": 0,
"cacheRatio": 0
}
],
"lifetime": {
"month": "",
"tokens": 0,
"inputTokens": 0,
"outputTokens": 0,
"cacheReadTokens": 0,
"messages": 0,
"toolCalls": 0,
"sessions": 0,
"costUsd": 0,
"models": 0,
"pricePerMillion": 0,
"costPerSession": 0,
"cacheRatio": 0
},
"seriesModels": [
""
],
"windowDays": 0,
"seriesDays": 0,
"from": "",
"to": "",
"generatedAt": 0
} Generated from the response schema — field values are placeholders, the shape is real.
SDK example
import { createNikcliClient } from "@nikcli-ai/sdk/httpapi"
const client = createNikcliClient()
await client.analytics.data({
...
}) Try it
Schemas
The 13 schemas reachable from these endpoints. Each is shown one level
deep; nested types link to their own entry below.
Names ending in _2, _3 and so on are the OpenAPI emitter
disambiguating same-named schemas declared by different HttpApi groups — they are distinct
shapes, not duplicates.
{ date: string sessions: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: AnalyticsTokenBreakdown cost: | number | "Infinity" | "-Infinity" | "NaN" toolCalls: | number | "Infinity" | "-Infinity" | "NaN" tools: { [key: string]: { calls: | number | "Infinity" | "-Infinity" | "NaN" success: | number | "Infinity" | "-Infinity" | "NaN" error: | number | "Infinity" | "-Infinity" | "NaN" } } providers: { [key: string]: { messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: | number | "Infinity" | "-Infinity" | "NaN" cost: | number | "Infinity" | "-Infinity" | "NaN" } } models: { [key: string]: { messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: | number | "Infinity" | "-Infinity" | "NaN" cost: | number | "Infinity" | "-Infinity" | "NaN" } } recordedAt: | number | "Infinity" | "-Infinity" | "NaN" }
| { totals: { tokens: | number | "Infinity" | "-Infinity" | "NaN" inputTokens: | number | "Infinity" | "-Infinity" | "NaN" outputTokens: | number | "Infinity" | "-Infinity" | "NaN" cacheReadTokens: | number | "Infinity" | "-Infinity" | "NaN" sessions: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" toolCalls: | number | "Infinity" | "-Infinity" | "NaN" costUsd: | number | "Infinity" | "-Infinity" | "NaN" models: | number | "Infinity" | "-Infinity" | "NaN" providers: | number | "Infinity" | "-Infinity" | "NaN" authors: | number | "Infinity" | "-Infinity" | "NaN" pricePerMillion: | number | "Infinity" | "-Infinity" | "NaN" costPerSession: | number | "Infinity" | "-Infinity" | "NaN" tokensPerSession: | number | "Infinity" | "-Infinity" | "NaN" cacheRatio: | | number | "Infinity" | "-Infinity" | "NaN" | null change: | | number | "Infinity" | "-Infinity" | "NaN" | null } models: AnalyticsDataModelStat[] authors: ({ author: string tokens: | number | "Infinity" | "-Infinity" | "NaN" sessions: | number | "Infinity" | "-Infinity" | "NaN" share: | number | "Infinity" | "-Infinity" | "NaN" models: | number | "Infinity" | "-Infinity" | "NaN" })[] series: ({ day: string byModel: { [key: string]: | number | "Infinity" | "-Infinity" | "NaN" } tokens: | number | "Infinity" | "-Infinity" | "NaN" sessions: | number | "Infinity" | "-Infinity" | "NaN" })[] months: AnalyticsDataPeriodStat[] lifetime: AnalyticsDataPeriodStat seriesModels: string[] windowDays: | number | "Infinity" | "-Infinity" | "NaN" seriesDays: | number | "Infinity" | "-Infinity" | "NaN" from: string to: string generatedAt: | number | "Infinity" | "-Infinity" | "NaN" } | null
{ model: string provider: string author: string tokens: | number | "Infinity" | "-Infinity" | "NaN" inputTokens: | number | "Infinity" | "-Infinity" | "NaN" outputTokens: | number | "Infinity" | "-Infinity" | "NaN" reasoningTokens: | number | "Infinity" | "-Infinity" | "NaN" cacheReadTokens: | number | "Infinity" | "-Infinity" | "NaN" cacheWriteTokens: | number | "Infinity" | "-Infinity" | "NaN" sessions: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" toolCalls: | number | "Infinity" | "-Infinity" | "NaN" costUsd: | number | "Infinity" | "-Infinity" | "NaN" share: | number | "Infinity" | "-Infinity" | "NaN" pricePerMillion: | number | "Infinity" | "-Infinity" | "NaN" costPerSession: | number | "Infinity" | "-Infinity" | "NaN" tokensPerSession: | number | "Infinity" | "-Infinity" | "NaN" cacheRatio: | | number | "Infinity" | "-Infinity" | "NaN" | null }
{ month: string | null tokens: | number | "Infinity" | "-Infinity" | "NaN" inputTokens: | number | "Infinity" | "-Infinity" | "NaN" outputTokens: | number | "Infinity" | "-Infinity" | "NaN" cacheReadTokens: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" toolCalls: | number | "Infinity" | "-Infinity" | "NaN" sessions: | number | "Infinity" | "-Infinity" | "NaN" costUsd: | number | "Infinity" | "-Infinity" | "NaN" models: | number | "Infinity" | "-Infinity" | "NaN" pricePerMillion: | number | "Infinity" | "-Infinity" | "NaN" costPerSession: | number | "Infinity" | "-Infinity" | "NaN" cacheRatio: | | number | "Infinity" | "-Infinity" | "NaN" | null }
{ version: 1 updatedAt: | number | "Infinity" | "-Infinity" | "NaN" totals: { sessions: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: AnalyticsTokenBreakdown cost: | number | "Infinity" | "-Infinity" | "NaN" toolCalls: | number | "Infinity" | "-Infinity" | "NaN" } byProvider: { [key: string]: AnalyticsProviderStat } byModel: { [key: string]: AnalyticsModelStat } byProject: { [key: string]: AnalyticsProjectStat } }
{ models: ({ key: string providerID: string modelID: string sessions: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: AnalyticsModelTokens cost: | number | "Infinity" | "-Infinity" | "NaN" firstUsed: | number | "Infinity" | "-Infinity" | "NaN" lastUsed: | number | "Infinity" | "-Infinity" | "NaN" totalTokens: | number | "Infinity" | "-Infinity" | "NaN" })[] providers: ({ id: string sessions: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: | number | "Infinity" | "-Infinity" | "NaN" cost: | number | "Infinity" | "-Infinity" | "NaN" })[] projects: ({ id: string sessions: | number | "Infinity" | "-Infinity" | "NaN" tokens: | number | "Infinity" | "-Infinity" | "NaN" cost: | number | "Infinity" | "-Infinity" | "NaN" lastActive: | number | "Infinity" | "-Infinity" | "NaN" })[] }
{ sessions: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: AnalyticsModelTokens cost: | number | "Infinity" | "-Infinity" | "NaN" firstUsed: | number | "Infinity" | "-Infinity" | "NaN" lastUsed: | number | "Infinity" | "-Infinity" | "NaN" }
{ input: | number | "Infinity" | "-Infinity" | "NaN" output: | number | "Infinity" | "-Infinity" | "NaN" reasoning: | number | "Infinity" | "-Infinity" | "NaN" }
{ sessions: | number | "Infinity" | "-Infinity" | "NaN" tokens: | number | "Infinity" | "-Infinity" | "NaN" cost: | number | "Infinity" | "-Infinity" | "NaN" lastActive: | number | "Infinity" | "-Infinity" | "NaN" }
{ sessions: | number | "Infinity" | "-Infinity" | "NaN" messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: | number | "Infinity" | "-Infinity" | "NaN" cost: | number | "Infinity" | "-Infinity" | "NaN" }
{ sessionID: string projectID: string directory: string title: string providerID: string modelID: string messages: | number | "Infinity" | "-Infinity" | "NaN" tokens: AnalyticsTokenBreakdown cost: | number | "Infinity" | "-Infinity" | "NaN" toolCalls: | number | "Infinity" | "-Infinity" | "NaN" duration: | number | "Infinity" | "-Infinity" | "NaN" time: { created: | number | "Infinity" | "-Infinity" | "NaN" completed: | number | "Infinity" | "-Infinity" | "NaN" } }
{ error: "Session not found" }
{ input: | number | "Infinity" | "-Infinity" | "NaN" output: | number | "Infinity" | "-Infinity" | "NaN" reasoning: | number | "Infinity" | "-Infinity" | "NaN" cacheRead: | number | "Infinity" | "-Infinity" | "NaN" cacheWrite: | number | "Infinity" | "-Infinity" | "NaN" }