list_harnesses
List harnesses
The agent harnesses the user has built from their recordings, each for a line of work. Call this first.
Takes no parameters.

io.github.aniketxdeyPublished by GitHub account aniketxdeyv0.3.0Updated Nov 7, 2026
Local screen and activity knowledge graph, served as context to computer-use agents.
Chronicle records your screen and system events locally and serves the resulting activity knowledge graph as context to AI agents over MCP.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Follow the launch instructions in the repository.
[Chronicle knowledge graph view of the sample workday]
A recording open on its knowledge graph, using the synthetic sample workday that chronicle demo loads. No real screen data is shown.
Chronicle records your screen and system events on your machine, writes context files and workflows from them, and builds them into agent harnesses that plug into any AI over MCP. Full documentation is at aniketxdey.github.io/chronicle.
Agents usually start every task knowing nothing about your computer. They don't know which ticket you were on, which file you had open, or what you looked up ten minutes ago. So you end up pasting context in by hand. Chronicle keeps that memory locally and lets the agent ask for it:
export.ts, that PR 882 is waiting on review, and what the export spec in Notion said.Everything is stored in one local folder (~/.chronicle), with no account and no telemetry. The only data that leaves the machine goes to model providers you give a key to (see Privacy).
Requires Python 3.10+. macOS is the main platform; Linux (X11) and Windows support is best effort.
chronicle context prints the same Markdown that the get_context MCP tool returns. On the sample workday it begins like this (trimmed):
To record your own work, run chronicle doctor to check permissions, then chronicle record 30m or chronicle serve and use the UI at http://127.0.0.1:3030.
Permissions and platform tools
xdotool and xprop. For screenshots install one of grim, gnome-screenshot, scrot, or ImageMagick import. Add xclip or wl-paste for the clipboard and xprintidle for idle time.brew install tesseract or apt install tesseract-ocr.The only required dependencies are FastAPI and uvicorn. The graph extra adds scikit-learn and scipy for better duplicate merging, and llm adds the OpenAI SDK and python-dotenv.
Record. A session runs for a set duration (90s, 30m, 2h) or until stopped. Every 5 seconds by default, the recorder samples the front app and window, the browser URL and tab title, and a screenshot. It also logs the system events app_switch, window_focus, url_change, clipboard, idle_start/idle_end, and session_start/session_stop. Screen text comes from the macOS Accessibility tree, and from tesseract OCR on the screenshot when an app exposes no text. Keystrokes are never recorded. Password managers, System Settings, and private browsing windows are skipped, and emails, API keys, JWTs, and card numbers are redacted before anything is written.
Build the graph. Each session gets its own graph shard. The shard is extended while recording and rebuilt once when the session ends, and frames captured outside a session go into hourly shards. The all-history graph is a SQL aggregation over the shards in which older shards count less (72-hour half-life by default). That keeps it focused on current work, and deleting a session just drops its shard.
BILL-142), PRs, code identifiers, people, projects, customers, meetings, sessions, and tasks. Topics are keyphrases such as "Acme export", scored by frequency, spread, casing, position, and dwell time. Tasks are activity segmented by topic.has_window, visited, on_site, shows, searched, about, co_occurs, switched_to and then (workflow transitions), spoke_in, discussed, copied, typed (text pushed through POST /add), and captured.Every node and edge records the time spent on it and the frames it came from, so an agent can cite its evidence. If an OpenAI key is available, a model also refines each recording when it ends (see LLM refinement).
Serve. get_context(task) returns a context pack with these parts:
Agents then drill down with query_graph, get_entity, search_history, and get_frame, which can return the screenshot itself.
These need uv on the PATH. Each runs uvx chronicle-context mcp and tells the model to call get_context before acting.
claude plugin marketplace add aniketxdey/chronicle, then claude plugin install chronicle@chronicle.gemini extensions install https://github.com/aniketxdey/chronicle.io.github.aniketxdey/chronicle.chronicle mcp install <client> merges the server into the client's config and keeps a .chronicle-backup copy of the old file. chronicle mcp config <client> prints the snippet instead, and chronicle mcp clients lists them all.
For any other client:
A stdio server can record on its own. Only one Chronicle process captures at a time: whichever holds ~/.chronicle/capture.lock. So an agent can call start_recording without chronicle serve running. Pass --no-record to turn this off.
chronicle serve exposes MCP at POST /mcp and supports protocol versions 2025-06-18, 2025-03-26, and 2024-11-05. Hosted agents need a public HTTPS URL, so put it behind a tunnel and set a token:
With a token set, every route except the UI shell and /health requires it. Open the UI once with ?token=… and it remembers the token. Requests with a non-local Origin header are rejected.
/mcp/<token> URL with no authentication. The search and fetch tools return the shapes that connectors and deep research expect.tools=[{"type": "mcp", "server_label": "chronicle", "server_url": URL, "require_approval": "never"}]. See examples/openai_responses.py.mcp-client-2025-04-04): mcp_servers=[{"type": "url", "url": URL, "name": "chronicle"}], alongside the computer-use tool. See examples/anthropic_computer_use.py.google-genai): pass an MCP ClientSession connected to chronicle mcp as a tool. chronicle mcp config gemini-api prints the snippet.chronicle mcp config http prints a curl call.Provider model names and beta flags change often, so treat these snippets as starting points and check the provider's MCP docs.
Resources: chronicle://context/current, chronicle://graph/summary, chronicle://sessions, and the templates chronicle://harness/{id}, chronicle://context-file/{id}, chronicle://workflow/{id}, chronicle://context/session/{id}, and chronicle://frame/{id}.
Prompts: use_my_computer_context(task), and learn_from_recording(session_id), which turns a recorded demonstration into steps an agent can repeat:
Then ask the agent: "Use the learn_from_recording prompt for session 1 and do it again for this receipt."
chronicle serve runs the UI at http://127.0.0.1:3030:
The REST API is documented at http://127.0.0.1:3030/docs. The most useful routes:
Capture interval, idle threshold, screenshots, OCR, clipboard, redaction, and retention are settings, edited in the UI or through POST /settings. Two settings mirror environment variables: graph_half_life_hours overrides CHRONICLE_HALF_LIFE_HOURS, while CHRONICLE_LLM takes precedence over llm_provider.
The heuristic graph knows apps, pages, tickets, files, and identifiers, but it can't tell that "Crusoe" is a company or that a page is a job posting. When a model is set up, it names the graph's nodes, works out what you did from system events and pages, and writes the context files. Set one up under Settings › Model with an OpenAI or Anthropic key, or point it at a local server such as Ollama or LM Studio. Without one, Chronicle runs fully offline: the graph stays heuristic and context files are assembled from the recording directly.
The key can also come from the environment or a .env in the current directory. A .env never overrides variables that are already set. Settings › Model or CHRONICLE_LLM=off turns the model off. GET /llm/status reports the provider and model in use and the last error.
Graph patches. The model reads the heaviest nodes along with their evidence: window titles, URLs and search queries, redacted screen text, and dwell time. It replies through strict function calls: add_entity, retype_node, rename_node, merge_nodes, add_relation, add_trait, record_action, drop_action, set_activity, and drop_node. A final pass over every named node merges what separate batches named twice. Actions must cite real frames and carry a status (completed, worked on, discussed, or viewed), because a screen shows state, not what you did. Actions and the system events behind them are kept inside each node, so the graph shows named things and the detail stays one click away. add_relation supports is_a, part_of, works_on, competes_with, located_in, researching, mentions, listed_in, uses, and related_to.
--rounds passes (default 2) and stops early when nothing new is proposed.kg_llm_patches and replayed after every rebuild, so refinement survives graph build. --reset removes them.source: "llm", and relations carry a confidence and an evidence quote. get_context lists activities first, then relations such as Crusoe —is_a→ company.Context files. For each of the eight presets, the model writes a document with the sections that kind of work needs and an "Open threads" list, citing frames. The evidence it was given is appended under "Recorded evidence".
Caching and failures.
--force.last_llm_error and never stop a recording. A failed context file falls back to the offline version.Other providers can be added with chronicle.llm.register(name, factory). A provider implements call_tools(system, user, tools) -> [{"name", "arguments"}] and complete(system, user) -> str.
Recordings, screenshots, and the graph stay in CHRONICLE_HOME. Data leaves the machine in three cases:
chronicle ask and the Ask box send the matching history to the provider you configure in Settings.PRIVACY.md has the details.
Releases are described in docs/PUBLISHING.md. The OSWorld benchmark harness is in bench/, and bench/PROTOCOL.md describes the evaluation. It hasn't been run yet, so there are no results.
MIT
Source: README.md at commit 4ff202a
List harnesses
The agent harnesses the user has built from their recordings, each for a line of work. Call this first.
Takes no parameters.
Get harness
One harness: its AGENTS.md, which says how to use it, and the list of its files.
idrequiredRead harness file
One file in a harness: AGENTS.md, a context file, or a workflow, with its small knowledge graph as text.
idrequiredpathrequiredSearch harness graph
Search a harness's knowledge graph engine: entities across its recordings, and the low-level system events that mention the words.
idrequiredqueryrequiredGet context file
One context file: standing instructions for this kind of work, the workflows it refers to, and its knowledge graph as text.
idrequiredGet workflow
One workflow: when to run it, its inputs, the steps in order, what to confirm with the person first, and its knowledge graph as text.
idrequiredGet knowledge graph
The knowledge graph of a recording, context file, or workflow, as nodes and edges in JSON or readable text.
idkindrequiredformatGet computer context
Context pack for a computer-use agent: what is on screen now, recent activity, habitual app/window transitions, the knowledge-graph entities relevant to the task, and cited evidence. Call this before acting.
taskpresetminutesmax_nodessession_idSearch history
Full-text search over captured screen text, system events, transcripts, and memories.
limitqueryrequiredapp_nameend_timestart_timecontent_typeQuery knowledge graph
Find knowledge-graph entities by text and/or kind, ranked by time spent and frequency.
kindlimitquerysession_idGet graph entity
One knowledge-graph entity with its neighbors, relations, and evidence frames. Accepts an id like 'ticket:bill-142' or a label.
idrequiredsession_idGraph summary
Counts by entity kind, the top entities of each kind, and the most common transitions.
session_idList tasks
What the user was doing, as a timeline of tasks (e.g. 'researching Forbes AI 50 · Crusoe', 4m) segmented from screen activity by topic. Each task has start/end, a verb, top terms, a topic cluster shared with other stints on the same topic, the pages and entities involved, and evidence frame ids.
sincesession_idGet frame
One captured frame: app, window, URL, text, nearby events. With include_image=true, also the screenshot.
frame_idrequiredinclude_imageActivity summary
Time per app, top windows, meetings, and a short narrative for a time range (default today).
end_timestart_timeList recordings
Recording sessions with status, duration, frame and event counts, and top apps.
limitStart recording
Record the screen and system events (app switches, window focus, URLs, clipboard, idle) for a preset duration such as '5m', '30m', or '2h'. The graph for the session is built when it ends.
labeldurationinterval_secsStop recording
Stop the running recording (or the given one) and build its knowledge graph.
session_idRebuild graph
Rebuild the knowledge graph for all history or one session from the stored frames and events.
session_idReview graph for curation
One batch of the knowledge graph with the rules and op schemas for curating it yourself. Use with graph_apply when the user wants their graph organized, including when Chronicle has no model of its own.
batchsession_idApply graph curation
Apply curation ops from graph_review to the local graph. Each op is checked, rejected ops come back with the reason, and tune_graph with reset=true removes them all.
opsrequiredsession_idTune graph with an LLM
Have the configured LLM (see Settings > Model or CHRONICLE_LLM) review the heuristic graph and patch it: add real-world entities, typed relations, and activity summaries, merge duplicates, clean labels, drop noise. Patches survive rebuilds; reset=true removes them. Off unless an LLM provider is configured.
forceresetroundssession_idList meetings
Meetings with speakers and transcript segments.
limitSearch (connector)
Search Chronicle history and the knowledge graph. Returns ids to pass to fetch.
queryrequiredFetch (connector)
Fetch the full record for an id returned by search (frame:N, audio:N, event:N, memory:N, node:<id>).
idrequired90% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
uv tool install "chronicle-context[graph]" # or: pipx install "chronicle-context[graph]"chronicle demo # load a synthetic workday, so you can try it without recordingchronicle context "finish the Acme export" # print what an agent would receivechronicle mcp install cursor # or claude-desktop, claude-code, codex, vscode, gemini-cli, ...# Computer context (Chronicle)Task: finish the Acme export
## What you were doing- 15:34-15:56 writing Acme Export spec · amount_usd (22m) [topic 1]- 16:28-16:48 coding export.ts · amount_usd (20m) [topic 2]- 16:50-17:02 coding Checks passed · Merge (12m) [topic 3]
## On screen now- Chrome · Checks · PR 882 at Sun 16:50 (frame 18)- URL: https://github.com/northwind/billing/actions- Visible text: ... Merge is waiting on Priya's second review. Acme export is still due Friday.
## Knowledge graph (all)- [topic] Acme export (`topic:acme-export`, 1h58m, frames 18, 16, 13)- [pr] PR 882 (`pr:882`, 2h42m, frames 18, 17, 16)- [file] export.ts (`file:export.ts`, 1h48m, frames 17, 11, 6)- [person] Maya Chen (`person:maya-chen`, 2h28m, frames 16, 14, 12){ "mcpServers": { "chronicle": { "command": "chronicle", "args": ["mcp"] } } }export CHRONICLE_TOKEN=$(openssl rand -hex 16)export CHRONICLE_PUBLIC_URL=https://<your-tunnel-host>chronicle serve &cloudflared tunnel --url http://127.0.0.1:3030 # or ngrok, tailscale funnel# MCP URL: $CHRONICLE_PUBLIC_URL/mcp/$CHRONICLE_TOKEN, or /mcp with "Authorization: Bearer $CHRONICLE_TOKEN"chronicle record 5m --label "file an expense report" # do the task oncechronicle context --session 1 # check what the agent will seechronicle serve [--host --port] web UI, REST API, and HTTP MCPchronicle record <duration> [--label --interval --detach]chronicle stop [id] · chronicle sessionschronicle graph build|show|find|node|export [--session N] (build --full re-extracts every shard)chronicle graph tasks [--session N --since "2h ago" --json]chronicle graph merges [--session N --threshold --json] (near-duplicate nodes the build merges)chronicle graph tune [--session N --rounds 2 --force --reset]chronicle context [task] [--minutes N --session N --json]chronicle mcp [stdio|clients|config <client>|install <client> [--path --dry-run]]chronicle search <q> · chronicle ask <question> · chronicle status · chronicle doctor · chronicle demouv tool install "chronicle-context[graph,llm]"echo "OPENAI_API_KEY=sk-..." >> ~/.chronicle/.envchronicle graph tune --session 1 # runs automatically when a recording endschronicle graph show --session 1 # activities and typed relations are listed firstgit clone https://github.com/aniketxdey/chronicle && cd chronicleuv pip install -e ".[dev,graph,llm]"pytestpython examples/stdio_client.py "finish the Acme export"npx @modelcontextprotocol/inspector --cli chronicle mcp --method tools/list