OpenChronicle Documentation

repository·main·Indexed 25 days ago

https://github.com/einsia/openchronicle

A local-first screen-context memory layer for tool-capable LLM agents on macOS 13+. OpenChronicle captures accessibility tree (AX) context and screenshots to create persistent Markdown and SQLite-based memory. It features a multi-layer architecture (Capture, Compression, Memory, and Query) and exposes processed memory to agents via the Model Context Protocol (MCP) at http://127.0.0.1:8742/mcp.

Tokens
24.2K
Snippets
37
Records
151
Agent score
81%

What's inside OpenChronicle

  1. Understand the OpenChronicle Memory Format

    main

    OpenChronicle stores memory as plain Markdown files located in ~/.openchronicle/memory/. Each file represents a single entity and follows a specific structure: YAML frontmatter followed by a list of append-only entries.

    Key characteristics:

    • One file per entity: Filenames use specific prefixes to denote the entity type.
    • Append-only: Information is never deleted; when facts change, old entries are struck through and new entries are appended.
    • Human-readable: Files can be read, searched with grep, or hand-edited.
    • Derived Index: The SQLite FTS index (index.db) is a mirror of these files. If you manually edit files, you must rebuild the index using openchronicle rebuild-index to prevent drift.
  2. Understand the Memory Organization Spec

    main

    OpenChronicle uses a structured memory organization system to store durable facts about users, projects, tools, and events. The system follows five core principles:

    1. Prefer silence over noise: The default action is to write nothing unless a fact is durable and significant.
    2. Self-contained entries: Every entry must be readable without needing surrounding context.
    3. Preserve timelines: When new information overrides old information, use the supersede action instead of deleting the old entry.
    4. No duplication: Skip recording if a similar fact was recently recorded.
    5. Route by nature of the fact: Assign facts to files based on what they are (e.g., a tool, a person, a project) rather than when they happened.
  3. Understand the Session Reducer Prompt structure

    main
    The session_reduce.md file defines the prompt used to summarize a user's work window into a structured session entry. It processes timeline blocks (pre-computed activity records) and preceding entries from the same day to create a concise, de-duplicated JSON summary. The prompt enforces strict rules regarding verbatim text preservation, context binding (associating people/files with specific apps), and the identification of behavioral regularities.
  4. Understand OpenChronicle session boundaries and storage

    main

    OpenChronicle organizes data using sessions and daily event files:

    • Sessions: A session is a bounded chunk of focused work. Sessions are triggered by events like idle time, app-switches, or timeouts. This ensures accurate time ranges for event-daily entries.
    • Daily Event Files: Data is stored in files named event-YYYY-MM-DD.md, which are sorted alphabetically by date.
    • On-disk State: The system uses a single process to manage tasks, which avoids IPC overhead and ensures index.db remains a single-writer. SQLite WAL (Write-Ahead Logging) is used to allow MCP readers to access the database concurrently.
  5. Understand the OpenChronicle Writer architecture

    main

    The Writer is a two-stage LLM pipeline designed to transform raw activity into structured logs and durable memory. It operates across session boundaries using two main components:

    1. S2 Reducer (writer/session_reducer.py): Writes incremental [flush] entries to event-YYYY-MM-DD.md during an active session and a final entry when the session closes.
    2. Classifier (writer/classifier.py): Periodically scans event-daily entries to extract durable facts and persists them to long-term memory files (e.g., user-/project-/tool-.md) using a tool-call loop.

    Key Timing Mechanisms:

    • Flush Tick: Occurs every session.flush_minutes (min 5). Runs the reducer with is_final=False to append [flush] entries to the daily log.
    • Classifier Tick: Occurs every classifier.interval_minutes (default 30, min 5). Processes entries since the last classified_end bookmark.
    • Session End: When a session ends, a terminal reduce is triggered, followed by a final classifier pass to cover the trailing window.
  6. Understand the OpenChronicle data processing pipeline

    main

    OpenChronicle uses a deterministic funnel to process data, prioritizing compression before classification to manage prompt sizes and ensure efficiency:

    1. S1 (Raw Snapshots) → Timeline: Raw AX snapshots are first compressed into a timeline.
    2. Timeline → S2 (Classified Facts): The timeline is then passed to a classifier. Because the classifier operates on a session-level summary rather than raw snapshots, it can efficiently extract durable facts without needing a separate triage step to decide if data is worth processing.
  7. Understand the Classifier module's role and input

    main

    The Classifier module processes closed user work sessions to extract long-term, classifiable facts for persistent memory. It operates on three primary input types:

    1. Session entries: Compressed output from the reducer (may contain inaccuracies or omissions).
    2. Timeline blocks: Verbatim-preserving activity slices used to verify specific phrasing or application usage.
    3. Preceding day: The end of the previous day's event file to ensure continuity and prevent duplication.

    Important: The Classifier must never write to event-*.md files; these are owned by the reducer.

  8. Understand the session flush and classification lifecycle

    main

    OpenChronicle uses a multi-stage pipeline to process session data:

    • Flush Tick (Incremental Reduce): While a session is active, a task runs every session.flush_minutes (default 5). It queries new timeline blocks and runs the reducer with is_final=False, appending a [flush]-tagged entry to the daily event file (e.g., event-YYYY-MM-DD.md).
    • Classifier Tick: Runs on a separate cadence (default every 30 minutes via classifier.interval_minutes) to classify entries since the last classified_end bookmark.
    • Terminal Reduce: When a session ends, a final reducer pass and a terminal classifier run to catch any trailing window of data that the periodic ticks missed.
  9. Understand the Capture layer

    main

    The Capture layer is the interface between OpenChronicle and macOS. It produces one JSON observation file per event and stores them in ~/.openchronicle/capture-buffer/. It uses two signal sources:

    1. mac-ax-watcher: An event-driven Swift binary that subscribes to Accessibility (AX) notifications (window focus, typing, title changes, etc.).
    2. Heartbeat timer: A fallback mechanism that triggers a capture every heartbeat_minutes (default 10) to ensure idle periods are recorded. Set heartbeat_minutes = 0 to disable this and use watcher-only mode.

    Each capture includes AX tree data, window metadata, and optionally a screenshot.

  10. Understand the classification and bookmarking mechanism

    main

    The classifier runs periodically to ensure long sessions produce durable facts without waiting for the session to close:

    • Intervals: The classifier fires every 30 minutes during an active session, plus one final pass at the end of the session.
    • Bookmarking: Each classification pass advances the session's classified_end bookmark. This prevents entries from being double-classified and allows for incremental progress during long-running sessions.
  11. Understand the OpenChronicle Architecture

    main

    OpenChronicle is a single daemon that operates through four distinct layers to transform raw capture events into durable Markdown memory:

    1. Capture Layer: Ingests events via mac-ax-watcher, performs debouncing/deduplication, and enriches data (focused element, visible text, URL) before writing to a JSON buffer.
    2. Compression Layer: Aggregates timeline blocks every 60s and uses a session manager to reduce active sessions into normalized blocks.
    3. Memory Layer: Uses an LLM-driven classifier to extract durable facts from daily event logs and organize them into specialized Markdown files (e.g., user-*.md, project-*.md).
    4. Query Layer: Provides access to the processed memory via a SQLite FTS5 search engine and an MCP (Model Context Protocol) server for use with AI agents like Claude Code or Cursor.