Documentation

Everything you need to integrate TailStats with your backend.

Installation

TailStats is a native macOS menu bar app that displays real-time metrics from multiple data sources.

Getting Started

  1. Download and open TailStats
  2. The app lives in your menu bar — click the icon to open
  3. Create your first card in Settings → Cards
  4. Optionally enable Launch at Login in Settings → General

Keyboard Shortcut: Press ⌘⇧T (Cmd+Shift+T) to toggle the window. Customize this in Settings → General.

Try It Now

Test TailStats with our live example endpoint:

https://www.tailstats.com/example1.json
View all examples

Card Configuration

Every card requires basic configuration regardless of which data method you use.

Required Settings

Setting Description
Name Display name for the card
URL API endpoint URL
Refresh Interval How often to fetch new data

Refresh Intervals

TailStats automatically polls your API at the configured interval:

Interval Use Case
30 seconds Real-time dashboards, live metrics
1 minute Active monitoring
5 minutes Standard dashboards
15 minutes Slow-changing data
30 minutes Daily summaries
1 hour Infrequent updates

Note: Data is also refreshed immediately when the app launches, you click the refresh button, or the device comes back online.

Data Sources

TailStats supports four ways to get data into cards:

Remote API

Poll any REST API at configurable intervals. Extract data with JSONPath or use structured responses.

Local Push

Push data via CLI, scripts, or webhooks. Perfect for CI/CD pipelines, cron jobs, and custom integrations.

File Watch

Monitor local files for changes. Display log files, config values, or any file content as live cards.

AI Agents

Track AI coding assistant usage. Built-in support for Claude Code and Codex CLI.

Authentication

TailStats supports multiple authentication methods for accessing protected APIs.

No Authentication

For public APIs, select "None".

Basic Authentication

HTTP Basic Auth with username and password.

Field Description
Username Your username or API user
Password Your password or API key

Credentials are sent as Authorization: Basic <base64> header.

Bearer Token

For APIs using bearer tokens (JWT, API keys, etc).

Field Description
Token Your bearer token or API key

Sent as Authorization: Bearer <token> header.

OAuth 2.0

For services using OAuth 2.0 client credentials flow.

Field Description
Client ID OAuth client identifier
Client Secret OAuth client secret
Token URL Token endpoint URL
Scope Optional OAuth scopes (space-separated)

TailStats handles token refresh automatically.

Custom Headers

Add any custom HTTP headers for APIs requiring special authentication or configuration.

Field Description
Header Name HTTP header name (e.g., X-API-Key)
Header Value Header value

You can add multiple custom headers per card.

Three Ways to Display Data

TailStats supports three methods for getting data into cards:

Method Best For
Simple Value Display whatever the endpoint returns — plain text, number, or raw response
Structured Response APIs you control — return data in TailStats format
JSONPath Extraction Any JSON API — extract specific values with JSONPath

Simple Value

The simplest method — whatever your endpoint returns is displayed directly as the card value. No parsing, no extraction.

How It Works

  1. Point TailStats at any URL
  2. The raw response body is displayed as the value
  3. Works with plain text, numbers, or any string response

Example Responses

42
→ displays "42"
Online
→ displays "Online"
$1,234.56
→ displays "$1,234.56"

Tip: Simple Value is perfect for quick integrations, status endpoints, or when you just need to display a single metric without building a full API response.

Structured Response

Build an API endpoint that returns data in TailStats format for full control over the display.

Response Structure

Your endpoint should return a JSON object with an items array and optional columns:

{
  "items": [ ... ],
  "columns": 2
}
Field Type Required Description
items CardData[] Yes Array of card items to display
columns number No Grid columns (1-4, default: 1)

Field Reference

Each item in the items array has the following structure:

Field Type Required Description
id string No Unique identifier (auto-generated if omitted)
title string Yes Main title text
subtitle string No Secondary text below title
type string Yes Value type (see Value Types)
value varies Yes The value to display (type depends on type field)
icon string No SF Symbol name (Apple platforms only)
emoji string No Emoji icon (cross-platform)
color string No Value text color
iconColor string No Icon/emoji background tint color
menuBar boolean No Show this value in macOS menu bar (default: false)
menuBarBackground string No Menu bar badge background color
rightLabel string No Text displayed on the right side
format string No Number formatting (see Value Formatting)

Value Types

The type field determines how value is interpreted and displayed.

string

Plain text value.

{ "title": "Status", "type": "string", "value": "Online" }

number

Numeric value (integer or decimal). Displays with thousands separator.

{ "title": "Users", "type": "number", "value": 1234 }
42 → "42"
1234 → "1,234"
3.14 → "3.14"
1234.56 → "1,234.56"

array

Array of numbers, displayed as a sparkline chart.

{ "title": "Traffic", "type": "array", "value": [10, 25, 15, 30, 20] }

progress

Progress bar (0.0 to 1.0 range).

{ "title": "Storage", "type": "progress", "value": 0.75 }
0.75 → 75% progress bar
0.5 → 50% progress bar

Card Types (15)

TailStats supports 15 different card types for displaying your data.

Basic Types

Type Description Example
string Text display with optional formatting "value": "Hello"
number Numeric with formatting (currency, compact, percent) "value": 1234.56
progress Horizontal progress bar (0-100% or 0-1 range) "value": 0.75
status Auto-colored indicator (success/warning/error/info) "value": "Online"
array Sparkline or bar chart visualization "value": [10, 20, 15, 30]

Rich Media Types

image

URL or base64-encoded image.

{ "type": "image", "value": "https://example.com/avatar.png" }

message

Chat bubble with sent/received modes.

{ "type": "message", "value": "Hello!", "displayMode": "received" }

map

Interactive map with markers.

{ "type": "map", "value": { "markers": [{ "lat": 37.7, "lng": -122.4, "label": "SF" }] } }

Advanced Types

timer

Live countdown/elapsed/duration display

{"target": 1705000000, "mode": "countdown"}

gauge

Circular dial indicator

{"value": 75, "max": 100, "unit": "%"}

link

Clickable URL (opens browser)

{"url": "https://...", "label": "Open"}

list

Vertical item list (max 10 visible)

[{"text": "Item 1", "icon": "circle"}]

qrcode

Generated QR code from string

"value": "https://example.com"

code

Syntax-highlighted code with copy button

{"source": "print('hi')", "language": "python"}

log

Scrollable log entries with level coloring (info, warn, error, debug)

[{"message": "Started", "level": "info", "timestamp": "12:00:00"}]

Display Rules

Conditional formatting engine that transforms card values based on rules. Up to 10 rules per card, 5 conditions per rule.

Condition Sources

Source Description
rawResponse Raw HTTP response body (before parsing)
extractedValue Value after JSONPath extraction
httpStatus HTTP status code (remote API cards only)
itemValue Individual item's display value

Operators

String Operators

  • contains / notContains
  • equals / notEquals
  • startsWith / endsWith
  • matchesRegex
  • isEmpty / isNotEmpty

Numeric Operators

  • greaterThan (>)
  • lessThan (<)
  • greaterOrEqual (>=)
  • lessOrEqual (<=)

Rule Actions

Action Description
overrideValue Replace displayed value
overrideIcon Change SF Symbol icon
overrideEmoji Change emoji
overrideColor Change color (name or hex)
overrideType Change card value type

Example Rule

{
  "conditions": [
    { "source": "extractedValue", "op": "greaterThan", "value": "80" }
  ],
  "conditionMode": "all",
  "action": {
    "overrideValue": "Critical",
    "overrideColor": "red",
    "overrideIcon": "exclamationmark.triangle.fill"
  },
  "enabled": true
}

Logic: Use conditionMode: "all" for AND logic, "any" for OR. First matching rule wins.

JSONPath Extraction

Extract specific values from any JSON API using JSONPath expressions. No API modifications required.

What is JSONPath?

JSONPath is a query language for JSON data. It lets you pinpoint exactly which value to extract from an API response.

Example: If an API returns:

{
  "data": {
    "users": 1250,
    "revenue": 45000
  }
}

Use $.data.users to extract 1250.

JSONPath Syntax

All paths start with $ (the root element).

Basic Navigation

Syntax Description Example
$.key Access a property $.data
$['key'] Property with special chars $['my-key']
[0] First array item $.items[0]
[-1] Last array item $.items[-1]
[*] All array items $.items[*].name
.. Search anywhere $..price

Advanced Features

Syntax Description Example
[0:5] Items 0 through 4 $.items[0:5]
[1,3,5] Specific items $.items[1,3,5]
[?(@.active)] Filter by field exists $.users[?(@.active)]
[?(@.age > 18)] Filter by condition $.users[?(@.age > 18)]

Filter Operators

Operator Description
== Equal
!= Not equal
< <= > >= Comparisons
&& AND
|| OR

Filter examples:

  • $.users[?(@.active == true)] — Active users only
  • $.items[?(@.price < 100)] — Items under $100
  • $.users[?(@.age > 18 && @.verified)] — Verified adults

Extraction Configuration

Each JSONPath extraction can be configured with:

Field Description
Path JSONPath expression (e.g., $.data.value)
Title Label shown above the value
Format Format string (see Value Formatting)
Icon SF Symbol name (e.g., person.fill)
Emoji Unicode emoji (e.g., 💰)
Color Icon/value color
Show in Menu Bar Display in macOS menu bar
Menu Bar Text Color Color of menu bar text
Menu Bar Background Badge background color

Multiple Extractions

Add multiple JSONPath extractions to show several values from the same API in one card.

Example: From a dashboard API, extract:

  1. Total users → $.metrics.users
  2. Revenue → $.metrics.revenue
  3. Active sessions → $.metrics.active

All values display together in a grid layout. Choose 1-4 columns.

Value Formatting

Control how numeric values are displayed using format strings.

Format String Syntax

Format strings follow this pattern:

type:option:modifier
Part Required Description
type Yes number, currency, or percent
option Sometimes Currency code or display option
modifier No Additional modifiers like cents

Number Formats

Format String Input Output Description
number 1234 1,234 Standard with thousands separator
number:compact 1234567 1.2M Compact notation (K, M, B)

Currency Formats

Format: currency:CODE or currency:CODE:cents

Format String Input Output
currency:USD 1234 $1,234.00
currency:EUR 1234 €1,234.00
currency:GBP 1234 £1,234.00
currency:JPY 1234 ¥1,234
currency:CAD 1234 CA$1,234.00
currency:AUD 1234 A$1,234.00

Currency from Cents

For APIs returning amounts in cents, add :cents modifier to divide by 100:

Format String Input Output
currency:USD:cents 12345 $123.45
currency:EUR:cents 12345 €123.45
currency:GBP:cents 12345 £123.45

Percentage Formats

Format String Input Output Description
percent 75 75% Whole number percentage
percent:decimal 0.75 75% Decimal (multiplied by 100)

Icons

Two icon options for cross-platform support.

Icon Resolution Order

TailStats resolves icons in this order:

  1. macOS/iOS: Use icon (SF Symbol) if provided and valid
  2. macOS/iOS fallback: Use emoji if icon is missing or invalid
  3. Android: Always use emoji (SF Symbols not supported)
  4. No icon: If neither is provided, no icon is displayed
Field Platform Description
icon Apple only SF Symbol name (e.g., "heart.fill")
emoji All platforms Emoji character (e.g., "❤️")

Recommendation: Always provide both icon and emoji for cross-platform compatibility.

Common SF Symbols

heart.fill
dollarsign.circle
chart.line.uptrend.xyaxis
server.rack
person.fill
checkmark.circle.fill
exclamationmark.triangle.fill
bell.fill
wifi

Full list: SF Symbols App

Colors

Color fields (color, iconColor, menuBarBackground) accept hex colors or named colors.

Hex Colors

"#FF5500"
"#F50"

Named Colors

red
green
blue
orange
yellow
purple
pink
gray
cyan
teal
indigo
brown

CLI Tool

Push data to TailStats cards from the command line, scripts, or automation.

Installation

curl -fsSL https://www.tailstats.com/install | sh

This installs the tailstats command to /usr/local/bin.

Push Command

Send data to a TailStats card:

tailstats push <card-id> [options]

Value Options

Option Description
--value "42" Simple value (string or number)
--json '{...}' JSON object with full card data
--file ~/data.json Read JSON from file

Display Options

Option Description
--title "CPU Usage" Set item title
--type number Value type: number, string, progress, status, array
--format percent Format: percent, currency:USD, number:compact
--icon "cpu" SF Symbol name
--emoji "📊" Emoji icon
--color red Value color (name or #hex)
--columns 2 Grid columns (1-4)

Menu Bar Options

Option Description
--menubar Show value in menu bar
--menubarBackground "#FF0000" Menu bar badge background color

Examples

tailstats push abc123 --value "42" --title "Active Users"
tailstats push abc123 --value "0.85" --type progress --title "CPU" --menubar
tailstats push abc123 --json '{"items":[{"title":"Revenue","type":"number","value":1234,"format":"currency:USD"}]}'

Notify Command

Send macOS notifications:

tailstats notify --message "Hello" [options]
Option Description
--title "Title" Notification title
--subtitle "Info" Subtitle text
--sound default Play notification sound
--open "https://..." URL to open on click
--execute "open /path" Command to run on click
--group "my-group" Group notifications together

Tip: Combine push with notify: tailstats push abc123 --value "Error" --notify "Build failed!"

Local Push Server

Three ways to push data to TailStats from local scripts and services.

HTTP Server

REST API on localhost for easy integration.

POST http://localhost:9876/push/<card-id>
Content-Type: application/json

{"items": [{"title": "Status", "type": "string", "value": "OK"}]}

WebSocket support available for persistent connections.

Unix Socket

Fastest option for local scripts. Low-latency IPC.

Socket Path ~/tmp/tailstats.sock

The CLI automatically uses Unix socket when available.

File Drop

Drop JSON files to push data. Works offline, no server needed.

Directory ~/Library/Application Support/TailStats/push/

Use tailstats push --file-drop to force file-based delivery.

Protocol Selection: CLI automatically picks the fastest available: Unix Socket → HTTP → File Drop.

File Watch Cards

Monitor local files and display their contents as live cards.

Parsing Modes

Raw Content

Display the entire file contents as text. Good for log files or simple text output.

JSONPath

Extract specific values from JSON files using JSONPath expressions. Same syntax as API extractions.

Items Array

Parse file as TailStats structured response format with items array.

Sandbox-Safe: TailStats uses secure file bookmarks to access files outside the sandbox. You'll be prompted to grant access once per file.

AI Agent Tracking

Built-in monitoring for AI coding assistants. Track usage, sessions, and costs.

🤖

Claude Code CLI

History File ~/.claude/history.jsonl
Metrics Sessions, messages, projects, token usage, costs

Codex CLI

Data Directory ~/.codex/
Metrics Sessions, generations, token usage

Displayed Metrics

  • Today's activity (messages, sessions)
  • Current session info
  • Last 7 days sparkline chart
  • Token usage and estimated costs

Enable in Settings: Go to Settings → AI Agents to enable tracking for each agent.

MCP Support

TailStats supports the Model Context Protocol (MCP), enabling AI assistants like Claude to directly interact with your dashboard cards.

What is MCP?

MCP (Model Context Protocol) is an open standard by Anthropic that allows AI assistants to use external tools. With TailStats MCP support, AI coding agents can list, read, update, and create cards.

Setup

1. Enable Local Push Server

In TailStats, go to Settings → General → Local Push Server and enable:

  • Local Push Server (master toggle)
  • HTTP & WebSocket

2. Configure Claude Code

Add to ~/.claude/settings.json:

{
"mcpServers": {
"tailstats": {
"type": "http",
"url": "http://localhost:9876/mcp"
}
}
}

3. Start Using

Ask Claude naturally:

  • "List my TailStats cards"
  • "Update the build-status card to 'Passing' with green color"
  • "Create a card called 'Deploy Status' with identifier 'deploy'"

Available Tools

list_cards

List all TailStats cards with their current values and status.

Parameters:

None

read_card

Read detailed data from a specific card.

Parameters:

Name Type Required Description
card string Yes Card name or identifier
update_card

Push new data to a Local Push card. Supports single values or multiple items.

Parameters:

Name Type Description
card string Card identifier (required)
value string Value to display (single item mode)
title string Title/label for the value
type string string, number, progress, status
color string Color name or hex (red, green, #FF5500)
icon string SF Symbol name
items array Array of items (multi-item mode)
columns integer Grid columns (1-4)
menuBar boolean Show in menu bar

Example (single item):

{ "card": "build-status", "value": "Passing", "color": "green", "menuBar": true }

Example (multi-item):

{
"card": "project-status",
"items": [
{"title": "Project", "value": "TailStats"},
{"title": "Status", "value": "Complete", "color": "green"}
],
"columns": 2
}
create_card

Create a new Local Push card for AI/automation updates.

Parameters:

Name Type Required Description
name string Yes Display name for the card
identifier string Yes Unique identifier for push updates

Use Cases

AI Coding Agent Tracking

Track Claude Code, Codex, or other AI agents in real-time. Show task status, project names, and completion states.

Build Pipeline Status

Display CI/CD status on your desktop. Show build, test, and deploy states with color-coded indicators.

Project Dashboard

Create a multi-project overview with status indicators for frontend, backend, and mobile progress.

Progress Tracking

Show completion progress for migrations, deployments, or long-running tasks with progress bars.

Security: MCP endpoint only accepts connections from localhost. No authentication required for local connections. All data stays on your machine.

Error Handling

TailStats handles errors gracefully to keep your dashboard running.

Error Types

Error Cause Display
Offline No internet connection Shows cached data with "offline" indicator
Timeout Request took longer than 30 seconds Shows cached data or error
Server Error HTTP 500+ response Shows error with status code
Not Found HTTP 400+ response Shows error with status code
Invalid URL Malformed URL Shows configuration error
Parse Error Response isn't valid JSON Shows parse error
Auth Error Authentication failed Shows auth error message
JSONPath Error Path doesn't match data Shows path error

Offline Behavior

When your device goes offline:

  1. Cards display their last successful data
  2. A "stale" indicator shows data may be outdated
  3. Last successful update time is displayed
  4. Data refreshes automatically when back online

Partial Failures

For cards with multiple JSONPath extractions:

  • Successfully extracted values are displayed
  • Failed extractions show individual errors
  • One failing extraction doesn't hide the others

Requirements

TailStats is a native macOS app built with SwiftUI.

System Requirements

  • macOS 13 (Ventura) or later
  • Apple Silicon or Intel Mac

Security

  • Credentials stored in macOS Keychain
  • Local push server binds to localhost only
  • Sandboxed file access with bookmarks

Examples

Structured Response: Dashboard

{
  "items": [
    {
      "title": "Revenue",
      "subtitle": "This month",
      "type": "number",
      "value": 12450.00,
      "icon": "dollarsign.circle",
      "emoji": "💰",
      "format": "currency:USD",
      "color": "green",
      "menuBar": true
    },
    {
      "title": "Users",
      "subtitle": "Active now",
      "type": "number",
      "value": 1234,
      "icon": "person.fill",
      "emoji": "👤",
      "format": "number"
    },
    {
      "title": "CPU Usage",
      "type": "progress",
      "value": 0.65,
      "icon": "cpu",
      "emoji": "💻"
    },
    {
      "title": "Traffic",
      "subtitle": "Last 7 days",
      "type": "array",
      "value": [120, 150, 180, 140, 200, 220, 190],
      "icon": "chart.line.uptrend.xyaxis",
      "emoji": "📈"
    }
  ],
  "columns": 2
}

JSONPath Examples

User Count

  • API returns: { "data": { "total_users": 1234567 } }
  • Path: $.data.total_users
  • Format: number:compact
  • Result: 1.2M

Revenue from Cents

  • API returns: { "revenue": { "total_cents": 1234500 } }
  • Path: $.revenue.total_cents
  • Format: currency:USD:cents
  • Result: $12,345.00

Filtered Count

  • API returns: { "servers": [{"status": "online"}, {"status": "offline"}, {"status": "online"}] }
  • Path: $.servers[?(@.status == 'online')]
  • Format: number
  • Result: 2

Authentication Examples

Bearer Token API

  • URL: https://api.example.com/metrics
  • Auth: Bearer Token
  • Token: sk_live_abc123...
  • Refresh: 5 minutes

Custom Header

  • URL: https://api.example.com/stats
  • Auth: None
  • Custom Header: X-API-Key = your-api-key