---
title: Recent CLI Activity — an audit log of what scripts and agents do through Omniscio's local server
---

# Recent CLI Activity — an audit log of what scripts and agents do through Omniscio's local server

## What it is

Omniscio runs a small local control server (`127.0.0.1:19519`) so scripts, hotkeys (AutoHotkey),
external AI agents, and integrations can drive Omniscio — spawn a session, open a project, run a recipe, change a
setting, search, and so on. **Recent CLI Activity** is a running record of those calls: a read-only audit card
that shows what came in over that server, so you can see what your automations have actually been doing.

It lives at **Settings → CLI Control → "Recent CLI Activity"**. Each row is one call — a plain-English summary
("Spawned a session in Marketing", "Opened the inbox", "Searched sessions"), a colored dot for the outcome
(green = success, amber = queued, red = denied or error), and how long ago it happened. Click a row to expand
the details: the exact endpoint and HTTP status, who called it (see "Who called it" below), the session it
spawned or relates to (a clickable link), and — for a spawn — a short preview of the prompt.

Two filters sit at the top:

- **Actions** (default) — only the calls that _did something_ (spawned a session, ran a recipe, changed a
  setting, opened/focused the UI). This is the view you usually want.
- **All** — also includes plain reads (listing sessions, searching, fetching state) for a complete picture.

The list is newest-first with a **Load more** button, and a trash button clears the whole history (you have to
type "clear" to confirm — it can't be undone).

## Where to find it

The card is in Settings → CLI Control, under the heading Recent CLI Activity. Rows appear there on
their own as calls arrive — there is nothing to switch on — and the same card is where the history
is cleared from, behind a confirmation you have to type out by hand.

## How it behaves

### What gets recorded vs skipped

Calls are sorted into two kinds:

- **Actions** — anything that changes state or steals focus: every non-GET call (POST/PATCH/DELETE), plus a few
  GETs that _do_ something rather than just read (bringing Omniscio to the foreground, opening the inbox, opening a
  project, opening a super prompt, spawning a session). These are kept for **90 days**.
- **Reads** — plain GETs that only fetch data (list sessions, search, read settings). These are noisier and
  less interesting after the fact, so they're kept for **7 days**.

On top of the time limits there's a hard ceiling of **50,000 rows total** — once it's full, the oldest entries
fall off first. A background cleaner enforces all three (time + cap) every few hours, so the log never grows
without bound. (All of this is local to your machine, in your Omniscio database — nothing is sent anywhere.)

**Deliberately not recorded:** liveness/health pings (`/ping`, `/status`, and the Zapier status check). Those
are polled constantly by integrations to check "is Omniscio up?", so logging them would bury the real activity in
noise.

### Who called it

Omniscio's control server uses one shared access token, so it can only record a _coarse_ idea of who made each call:

- **CLI token** — a script, hotkey, or external tool using the shared bearer token.
- **In-app session** — another Omniscio agent that authenticated as itself.
- **Anonymous** — an unauthenticated call (e.g. a public health ping).

**The bearer token itself is never stored** — only this coarse category. So the log tells you _what kind_ of
caller did something, not a secret you'd have to protect.

When a call came from one of your Omniscio agents that identified itself (via session provenance — see
[session provenance](session-provenance.md)), the expanded row shows a clickable **"Triggered by"** link back
to that session. A spawn also links to the **session it created**. So you can trace a spawn in the activity log
straight to the agent that asked for it and the session that resulted.

### How the capture works (and why it's safe)

Recording is **best-effort and happens after the response is already sent** — it is never in the path of the
actual call. Two cases:

- **Spawning a session** (the most important action) is recorded at the moment the spawn is created, _not_ off
  the network connection — so even if the script that asked for it disconnects immediately, the spawn still
  shows up in the log.
- **Everything else** is recorded by a catch-all that fires once the response finishes.

Each call is logged **at most once**, and a logging failure can never break or slow down the call it was trying
to record — at worst a single entry is silently dropped (and counted). The log is an audit breadcrumb, **not a
security control**: the control server is already restricted to your own machine and gated by the bearer token.

## For agents

### A note on double-recording (for agents with repo access)

Internally, each authenticated CLI hit produces **two** writes: a long-standing `cli_control` usage-analytics
counter (aggregate "how often is the CLI used" data, no per-call UI) and the new `cli_activity_log` row that
backs this card. They serve different audiences, so the overlap is intentional and documented as known debt; a
future cleanup could collapse them, but it isn't worth doing pre-emptively. Full invariants + tests:
[`.claude/memory/contracts/cli-activity-log-contract.md`](../../.claude/memory/contracts/cli-activity-log-contract.md).

### Under the hood (for agents with repo access)

- Capture: `installCliActivityCapture(req, res, …)` at the top of `handleRequest` in
  `src/main/services/cli/cli-server.ts` (Tier-B, off `res` `finish`/`close`); spawns are recorded at the chokepoint
  inside `pacedCreateSessionFromCli` (Tier-A) via `recordCliActivity`, with `markActivityCaptured(req)` so the
  Tier-B hook doesn't double-write. Classification + skip-list + outcome mapping live in
  `src/main/services/cli/cli-activity-log.ts`.
- Storage: the `cli_activity_log` table (migration `20260604044430-add-cli-activity-log`, 2 indexes; the
  `request_id` + `cron_job_id` correlation columns added by `20260717235136-add-request-id-and-cron-job-id-to-cli-activity-log`).
  No token column — caller identity is the coarse `caller_kind`, and the two correlation columns are non-secret
  ids only: `request_id` is the per-request `req-xxxx` ref also echoed to the caller as `X-AMC-Request-Id` (so a
  logged row can be traced to the exact call the caller saw), and `cron_job_id` is the validated cron origin when
  a local `script`-type cron drove the call. Queries (`insertCliActivity`, cursor-paged
  `listCliActivity`, `clearCliActivity`, `pruneCliActivity`) in `src/main/db/queries-cli-activity.ts`.
- Retention: `cli-activity-pruner.ts` runs `pruneCliActivity` every 6 hours — 90-day actions, 7-day reads,
  50,000-row hard cap (oldest deleted first).
- UI: `CliActivityLog.tsx` + `CliActivityRow.tsx` (Settings → CLI Control), over the `cli-activity:list` /
  `cli-activity:clear` IPC channels.
- Full invariants + tests: `.claude/memory/contracts/cli-activity-log-contract.md`.

## Related

The server these rows are about — what it is, how a caller is authenticated and the full route
catalog — is on the [CLI control](cli-control.md) page. Calls that ask for a human decision rather
than acting immediately land in a queue described on
[CLI pending actions](cli-pending-actions.md), and how a row is traced back to the agent that made
it is on [session provenance](session-provenance.md).