Activity Record
Activity Record stores normalized local activity facts in:
~/.Arkloop/activity-record/activity.db
Use bounded SQL queries. Always include a time range or LIMIT.
Tables
activity_events
| Column | Description |
|---|---|
occurred_at |
RFC3339 timestamp |
source |
Source key (see Sources below) |
source_event_id |
Stable dedup key |
app |
App or profile name |
window_title |
Active window title when available |
url |
URL when available |
action |
Event action |
title |
Short event title |
text |
Longer text when available |
metadata_json |
Source-specific JSON |
ref_kind, ref_key |
Optional reference pointer |
source_cursors
Incremental sync state per source. Diagnostics only.
activity_refs
Optional reference files.
Sources and Actions
chrome — Chromium Browser History
Covers Chrome, Chrome Canary, Chromium, Edge, Brave. Multi-profile.
| Action | Title | Metadata |
|---|---|---|
visited |
Page title | profile, duration_sec, foreground_sec |
downloaded |
Filename | profile, path, size_bytes, mime_type |
searched |
Search term | profile, normalized_term |
safari — Safari History (macOS)
| Action | Title | Metadata |
|---|---|---|
visited |
Page title | domain, visit_count, load_successful, score |
screentime — macOS Screen Time (knowledgeC.db)
| Action | Title | Metadata |
|---|---|---|
app_used |
App name | bundle_id, source_bundle, device_id, duration_sec |
screen_on |
"screen on" | duration_sec |
screen_off |
"screen off" | duration_sec |
notification_received |
App name | bundle_id |
media_used |
App name | bundle_id, duration_sec, url, media_url |
media_playing |
Track title or app | bundle_id, duration_sec, playing, artist, album, genre |
web_used |
Domain | bundle_id, web_domain, duration_sec |
bluetooth_connected |
Device name | device_name, device_type, is_apple_audio_device, duration_sec |
bluetooth_disconnected |
Device name | Same as above |
shell — Shell Command History
Reads ~/.zsh_history and ~/.bash_history. Deduplicated by command hash.
| Action | Title | Metadata |
|---|---|---|
command |
Command (truncated) | shell, line_num. Full command in text column. |
codex — Claude Code Sessions
| Action | Title | Metadata |
|---|---|---|
prompted |
Prompt text | session_id, cwd |
received |
Response text | session_id, cwd, model |
window — Active Window Tracking (daemon)
| Action | Title | Metadata |
|---|---|---|
focused |
"App - Window Title" | duration_sec, pid |
idle_start |
"idle" | idle_threshold_sec |
idle_end |
"idle" | — |
keyboard — Keystroke Counting (daemon)
| Action | Title | Metadata |
|---|---|---|
keystroke_count |
"N keystrokes in App" | count, interval_sec, app, window_title |
mouse — Mouse Activity (daemon)
| Action | Title | Metadata |
|---|---|---|
mouse_activity |
"N clicks, N scrolls in App" | clicks, scrolls, interval_sec, app, window_title |
clipboard — Clipboard Changes (daemon)
| Action | Title | Metadata |
|---|---|---|
clipboard_changed |
Content preview | length. Full text in text column when enabled. |
ax — Screen Content via Accessibility Tree (daemon, macOS)
Captures visible text from the focused window by walking the macOS accessibility tree. No screen capture or OCR involved — zero WindowServer overhead.
| Action | Title | Metadata |
|---|---|---|
ax_snapshot |
"App - Window Title" | element_count, text_length, walk_duration_ms, content_hash, pid, truncated, truncation_reason |
Text content: full visible text from the focused window is stored in the text column. Content is deduplicated by SHA-256 hash — identical screens do not produce repeated events.
Browser URL: extracted via AXDocument attribute when the focused app is a browser. Available in the url column.
Excluded apps: password managers (1Password, Bitwarden, KeePassXC, LastPass, Dashlane, Keychain Access) and incognito/private browsing windows are skipped entirely.
audio — Microphone Transcription (daemon)
Transcribes microphone speech via an OpenAI-compatible API. Each segment passes an RMS gate, voice-activity detection, and music filtering before transcription, so only segments containing speech are stored.
| Action | Title | Metadata |
|---|---|---|
audio_transcription |
Transcript preview | duration_sec, device, language, model. Full transcript in text column. |
Text content: the full transcript of each speech segment is stored in the text column. Overlapping words between consecutive segments are deduplicated.
Examples
Recent activity across all sources:
SELECT occurred_at, source, action, title, url
FROM activity_events
ORDER BY occurred_at DESC
LIMIT 50;
What apps were used today (Screen Time):
SELECT title AS app, COUNT(*) AS sessions,
SUM(json_extract(metadata_json, '$.duration_sec')) AS total_sec
FROM activity_events
WHERE source = 'screentime' AND action = 'app_used'
AND occurred_at >= datetime('now', '-1 day')
GROUP BY title ORDER BY total_sec DESC
LIMIT 20;
Recent browser searches:
SELECT occurred_at, title AS search_term, url
FROM activity_events
WHERE source = 'chrome' AND action = 'searched'
AND occurred_at >= datetime('now', '-7 days')
ORDER BY occurred_at DESC
LIMIT 50;
Recent shell commands:
SELECT occurred_at, text AS command
FROM activity_events
WHERE source = 'shell' AND action = 'command'
ORDER BY occurred_at DESC
LIMIT 30;
Bluetooth device connections:
SELECT occurred_at, action, title AS device,
json_extract(metadata_json, '$.duration_sec') AS duration
FROM activity_events
WHERE source = 'screentime' AND action LIKE 'bluetooth%'
ORDER BY occurred_at DESC;
Music playing history:
SELECT occurred_at, title,
json_extract(metadata_json, '$.artist') AS artist,
json_extract(metadata_json, '$.album') AS album
FROM activity_events
WHERE source = 'screentime' AND action = 'media_playing'
ORDER BY occurred_at DESC
LIMIT 20;
Window focus timeline:
SELECT occurred_at, app, window_title,
json_extract(metadata_json, '$.duration_sec') AS sec
FROM activity_events
WHERE source = 'window' AND action = 'focused'
AND occurred_at >= datetime('now', '-1 day')
ORDER BY occurred_at DESC
LIMIT 50;
Recent screen content (what the user is reading/doing):
SELECT occurred_at, app, window_title, url,
substr(text, 1, 500) AS screen_text,
json_extract(metadata_json, '$.element_count') AS elements
FROM activity_events
WHERE source = 'ax'
AND occurred_at >= datetime('now', '-1 day')
ORDER BY occurred_at DESC
LIMIT 30;
Screen content for a specific app:
SELECT occurred_at, window_title, url,
substr(text, 1, 800) AS screen_text
FROM activity_events
WHERE source = 'ax' AND app = 'Google Chrome'
AND occurred_at >= datetime('now', '-4 hours')
ORDER BY occurred_at DESC
LIMIT 20;
Recent audio transcripts (meetings, conversations):
SELECT occurred_at,
substr(text, 1, 500) AS transcript,
json_extract(metadata_json, '$.duration_sec') AS dur
FROM activity_events
WHERE source = 'audio'
AND occurred_at >= datetime('now', '-1 day')
ORDER BY occurred_at DESC
LIMIT 30;
Memory Rules
Write only durable context to memory_write:
- Stable preferences and habits.
- Ongoing projects and decisions.
- Important events with useful future context.
- Clear changes in workflow or priorities.
Do not write Notebook entries. Do not persist raw OCR, raw transcripts, app-switch logs, secrets, one-time codes, or unverified fragments.