In my first post I wrote about why I built chron, an MCP server that logs every AI conversation to local SQLite. This one is about what I built next: streaming those events into CrowdStrike LogScale so security teams can see AI activity across their org.
The problem with local-only logging
chron stores everything locally. That's good for individuals, your data, your machine, no cloud. But for an org with 50 developers all using Claude or Cursor, "local SQLite per machine" doesn't give anyone a picture of what's happening org wide.
Security teams need a centralized view. And they already have one: their SIEM.
Why LogScale (Humio)
CrowdStrike acquired Humio in 2021 and rebranded it LogScale. It's one of the fastest log ingestion systems available, and it's already deployed at most enterprises that take security seriously. If I could get chron events into LogScale, I'd be sending data somewhere security teams already look.
LogScale has a clean structured ingest API. You POST an array of events, each with a timestamp and key-value attributes. No schema to define upfront, it's schema less by default.
The relay design
I wanted the integration to be genuinely zero-friction for chron's critical path. Logging a message should never slow down because the relay is having a bad day.
The solution: fire-and-forget via setImmediate.
export function emitEvent(payload: ChronEventPayload): void {
const url = process.env.CHRON_LOGSCALE_URL;
const token = process.env.CHRON_LOGSCALE_TOKEN;
if (!url || !token) return;
setImmediate(() =>
fetch(url, {
method: 'POST',
headers: {
'Authorization': Bearer ${token},
'Content-Type': 'application/json',
},
body: buildLogScalePayload(payload),
}).catch(() => undefined)
);
}
setImmediate pushes the fetch to the next iteration of the event loop, after the current operation completes. The .catch(() => undefined) means a failed relay never surfaces as an error. The audit log always writes to local SQLite first. The relay is best effort.
Three event types
chron emits exactly three event types to LogScale:
session_started - when a new AI session begins. Includes the AI tool name and an anonymized machine ID (SHA-256 of hostname, truncated to 16 chars).
message_logged - when a message is recorded. Includes role (user/assistant), timestamp, session prefix. Message content never leaves the machine.
secret_detected - when the auto-scanner finds a credential in a user message. Includes detection type (aws_key, github_token, etc.) and a masked value. The real value stays local.
That last point matters: chron's secret detection is designed to alert without exfiltrating. The masked value in LogScale tells the CISO "a GitHub token appeared in a developer's AI prompt on this machine at this time." The token itself is not in LogScale.
The connect CLI
Getting the credentials set up should be one command, not a documentation page.
chron connect crowdstrike
This prompts for your LogScale URL and ingest token, sends a real test event, validates the HTTP 200 response, and saves the config to ~/.chron/config.json. It also prints the exact env block to paste into ~/.claude.json so the credentials load automatically on every Claude Code session.
Five dashboards, ready to import
The hardest part of a new data source isn't the ingest — it's getting useful queries in front of the people who need them. I shipped five LQL queries and one importable dashboard YAML with chron 0.1.14.
The dashboard covers:
AI tool usage by count (which tools are developers actually using)
Daily active developers by machine
Sessions per developer
Secret detections by type over time
API key alert query for scheduled SOC alerting
Import the YAML into LogScale and all five widgets are live. If you have chron running on even one machine, you'll see data immediately.
What's next
The relay currently supports LogScale and a generic HTTP endpoint (CHRON_RELAY_URL). Splunk, Elastic, and Datadog integrations are on the roadmap, the event schema is the same, just different destination formats.
If you're running LogScale and want to try it:
npx -y chron-mcp
chron connect crowdstrike
Restart Claude Code or Cursor, have a conversation, and watch the events appear in your LogScale stream.
github.com/sirinivask/chron

Top comments (0)