---
audience: everyone
summary: "Online, idle, busy, appear offline \u2014 and how ScaiWave tracks it."
title: Presence and availability
path: concepts/presence
status: published
---

# Presence and availability

Presence is the green/yellow/red dot on every avatar. It's what other
people see when they're deciding whether to message you.

## States

| State | What it means | When it's set |
|---|---|---|
| `online` | You're at your keyboard. | Default while you're using ScaiWave. |
| `idle` | You're signed in but not active. | Auto: 5 minutes without DOM events (configurable). |
| `busy` | "Don't ping me unless it's urgent." | Manual: profile picker. |
| `appear_offline` | Pretend you're not here. | Manual: profile picker. |
| `offline` | Not signed in anywhere. | Automatic. |

## How it works

The client publishes a heartbeat every 30 seconds while focused. The
server stores `(participant_id, state, last_seen)` in Redis with a
2-minute TTL. If two heartbeats pass without a refresh, the server
demotes the participant to `offline`.

Auto-idle is client-driven: `client/src/lib/activity.ts` watches
keyboard, mouse, scroll, and focus events. Five minutes without any
of them → flip to `idle` (publishes the update). On any new event,
flip back to `online`.

The `busy` and `appear_offline` states are sticky — they don't auto-
clear. To go back to `online`, pick **Switch to auto-detect** from
the profile picker.

## Multi-device

If you're signed in on three devices, your effective presence is the
"most awake" one. If laptop is `idle`, phone is `online`, desktop is
`offline` → you appear `online`. The server unions device states per
participant.

## Privacy

`appear_offline` shows you as `offline` to everyone *except* people
who already had a DM with you in the last 24 hours (so the
just-talked-to-you-now case still works). You see the real states
of others; they don't see yours.

## AI participants

Model and helper participants always show as `online`. They don't
sleep.

## Presence in the API

- `GET /v1/presence?ids=…` — batch-fetch presence for a list of
  participant ids. Returns `{participant_id: state}`.
- Real-time updates: subscribe to `presence` WebSocket events.

## Where to go next

- Tutorial: [Manage your availability](/docs/scaiwave/tutorials/first-steps/manage-your-availability).
- API: [Presence](/docs/scaiwave/reference/api/presence-and-state).
