agents-chronicle 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. agents_chronicle-0.1.0/.github/workflows/release.yml +95 -0
  2. agents_chronicle-0.1.0/.gitignore +7 -0
  3. agents_chronicle-0.1.0/.python-version +1 -0
  4. agents_chronicle-0.1.0/PKG-INFO +337 -0
  5. agents_chronicle-0.1.0/README.md +324 -0
  6. agents_chronicle-0.1.0/docs/diagrams/analysis.excalidraw.svg +8 -0
  7. agents_chronicle-0.1.0/docs/diagrams/architecture.excalidraw.svg +8 -0
  8. agents_chronicle-0.1.0/packaging/macos/Chronicle.icns +0 -0
  9. agents_chronicle-0.1.0/packaging/macos/Chronicle.spec +54 -0
  10. agents_chronicle-0.1.0/packaging/macos/build.sh +55 -0
  11. agents_chronicle-0.1.0/packaging/macos/chronicle_app.py +22 -0
  12. agents_chronicle-0.1.0/packaging/macos/entitlements.plist +11 -0
  13. agents_chronicle-0.1.0/packaging/macos/icon.png +0 -0
  14. agents_chronicle-0.1.0/packaging/macos/make_icon.py +65 -0
  15. agents_chronicle-0.1.0/pyproject.toml +37 -0
  16. agents_chronicle-0.1.0/src/chronicle/__init__.py +3 -0
  17. agents_chronicle-0.1.0/src/chronicle/__main__.py +3 -0
  18. agents_chronicle-0.1.0/src/chronicle/agents.py +20 -0
  19. agents_chronicle-0.1.0/src/chronicle/analyze.py +330 -0
  20. agents_chronicle-0.1.0/src/chronicle/bob_parser.py +135 -0
  21. agents_chronicle-0.1.0/src/chronicle/cli.py +835 -0
  22. agents_chronicle-0.1.0/src/chronicle/codex_parser.py +742 -0
  23. agents_chronicle-0.1.0/src/chronicle/config.py +258 -0
  24. agents_chronicle-0.1.0/src/chronicle/connectors.py +406 -0
  25. agents_chronicle-0.1.0/src/chronicle/copilot_parser.py +481 -0
  26. agents_chronicle-0.1.0/src/chronicle/db.py +416 -0
  27. agents_chronicle-0.1.0/src/chronicle/desktop.py +447 -0
  28. agents_chronicle-0.1.0/src/chronicle/digest.py +194 -0
  29. agents_chronicle-0.1.0/src/chronicle/export_md.py +210 -0
  30. agents_chronicle-0.1.0/src/chronicle/glossary.py +363 -0
  31. agents_chronicle-0.1.0/src/chronicle/hooks.py +126 -0
  32. agents_chronicle-0.1.0/src/chronicle/ingest.py +956 -0
  33. agents_chronicle-0.1.0/src/chronicle/install.py +302 -0
  34. agents_chronicle-0.1.0/src/chronicle/llm.py +244 -0
  35. agents_chronicle-0.1.0/src/chronicle/mcp_server.py +322 -0
  36. agents_chronicle-0.1.0/src/chronicle/parser.py +873 -0
  37. agents_chronicle-0.1.0/src/chronicle/pricing.py +168 -0
  38. agents_chronicle-0.1.0/src/chronicle/redact.py +42 -0
  39. agents_chronicle-0.1.0/src/chronicle/reviews.py +194 -0
  40. agents_chronicle-0.1.0/src/chronicle/search.py +151 -0
  41. agents_chronicle-0.1.0/src/chronicle/server.py +798 -0
  42. agents_chronicle-0.1.0/src/chronicle/synthesize.py +277 -0
  43. agents_chronicle-0.1.0/src/chronicle/util.py +215 -0
  44. agents_chronicle-0.1.0/src/chronicle/views.py +211 -0
  45. agents_chronicle-0.1.0/src/chronicle/web/app.css +814 -0
  46. agents_chronicle-0.1.0/src/chronicle/web/app.js +2278 -0
  47. agents_chronicle-0.1.0/src/chronicle/web/index.html +45 -0
  48. agents_chronicle-0.1.0/src/chronicle/worker.py +251 -0
  49. agents_chronicle-0.1.0/tests/codex_fixture.py +177 -0
  50. agents_chronicle-0.1.0/tests/conftest.py +267 -0
  51. agents_chronicle-0.1.0/tests/copilot_fixture.py +119 -0
  52. agents_chronicle-0.1.0/tests/test_analysis.py +196 -0
  53. agents_chronicle-0.1.0/tests/test_codex.py +156 -0
  54. agents_chronicle-0.1.0/tests/test_copilot_bob.py +103 -0
  55. agents_chronicle-0.1.0/tests/test_desktop.py +91 -0
  56. agents_chronicle-0.1.0/tests/test_glossary.py +92 -0
  57. agents_chronicle-0.1.0/tests/test_ingest.py +116 -0
  58. agents_chronicle-0.1.0/tests/test_integration.py +184 -0
  59. agents_chronicle-0.1.0/tests/test_parser.py +135 -0
  60. agents_chronicle-0.1.0/tests/test_regressions.py +209 -0
  61. agents_chronicle-0.1.0/uv.lock +474 -0
@@ -0,0 +1,95 @@
1
+ name: Release
2
+
3
+ # Publishing a GitHub release tagged vX.Y.Z (matching pyproject.toml) runs the tests, publishes
4
+ # agents-chronicle to PyPI (trusted publishing, no token) and attaches Chronicle-X.Y.Z-arm64.dmg to the release.
5
+ #
6
+ # The DMG is signed and notarized when these repository secrets exist, otherwise it is ad-hoc signed:
7
+ # MACOS_CERT_P12 base64 of the "Developer ID Application" certificate + key (.p12)
8
+ # MACOS_CERT_PASSWORD its export password
9
+ # MACOS_CODESIGN_IDENTITY e.g. "Developer ID Application: Your Name (TEAMID)"
10
+ # APPLE_ID, APPLE_TEAM_ID, APPLE_APP_PASSWORD for notarytool (app-specific password)
11
+
12
+ on:
13
+ release:
14
+ types: [published]
15
+ workflow_dispatch: # dry run: builds the DMG as a workflow artifact, publishes nothing
16
+
17
+ jobs:
18
+ test:
19
+ runs-on: macos-14
20
+ steps:
21
+ - uses: actions/checkout@v6
22
+ - uses: astral-sh/setup-uv@v7
23
+ - name: Verify tag matches package version
24
+ if: github.event_name == 'release'
25
+ run: |
26
+ TAG="${GITHUB_REF_NAME#v}"
27
+ PKG=$(uv run --no-project python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
28
+ if [ "$TAG" != "$PKG" ]; then
29
+ echo "::error::Tag v$TAG does not match pyproject.toml version $PKG"
30
+ exit 1
31
+ fi
32
+ - run: uv run --locked pytest -q
33
+
34
+ pypi:
35
+ needs: test
36
+ if: github.event_name == 'release'
37
+ runs-on: ubuntu-latest
38
+ environment: pypi
39
+ permissions:
40
+ contents: read # checkout (a permissions block drops every default, and the repository is private)
41
+ id-token: write # OIDC for PyPI trusted publishing
42
+ steps:
43
+ - uses: actions/checkout@v6
44
+ - uses: astral-sh/setup-uv@v7
45
+ - run: uv build
46
+ - uses: pypa/gh-action-pypi-publish@release/v1
47
+
48
+ macos-app:
49
+ needs: test
50
+ runs-on: macos-14 # Apple silicon; PyInstaller cannot cross-build, so an Intel build needs an Intel runner
51
+ permissions:
52
+ contents: write # upload the DMG to the release
53
+ env:
54
+ HAS_CERT: ${{ secrets.MACOS_CERT_P12 != '' }}
55
+ steps:
56
+ - uses: actions/checkout@v6
57
+ - uses: astral-sh/setup-uv@v7
58
+
59
+ - name: Import signing certificate
60
+ if: env.HAS_CERT == 'true'
61
+ env:
62
+ MACOS_CERT_P12: ${{ secrets.MACOS_CERT_P12 }}
63
+ MACOS_CERT_PASSWORD: ${{ secrets.MACOS_CERT_PASSWORD }}
64
+ run: |
65
+ KC="$RUNNER_TEMP/signing.keychain-db"
66
+ KCPW=$(uuidgen)
67
+ security create-keychain -p "$KCPW" "$KC"
68
+ security set-keychain-settings -lut 21600 "$KC"
69
+ security unlock-keychain -p "$KCPW" "$KC"
70
+ echo "$MACOS_CERT_P12" | base64 --decode > "$RUNNER_TEMP/cert.p12"
71
+ security import "$RUNNER_TEMP/cert.p12" -P "$MACOS_CERT_PASSWORD" -A -t cert -f pkcs12 -k "$KC"
72
+ security set-key-partition-list -S apple-tool:,apple: -k "$KCPW" "$KC"
73
+ security list-keychains -d user -s "$KC" $(security list-keychains -d user | tr -d '"')
74
+ rm "$RUNNER_TEMP/cert.p12"
75
+
76
+ - name: Build Chronicle.app and DMG
77
+ env:
78
+ CHRONICLE_CODESIGN_IDENTITY: ${{ env.HAS_CERT == 'true' && secrets.MACOS_CODESIGN_IDENTITY || '' }}
79
+ APPLE_ID: ${{ secrets.APPLE_ID }}
80
+ APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
81
+ APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
82
+ run: ./packaging/macos/build.sh
83
+
84
+ - name: Attach DMG to the release
85
+ if: github.event_name == 'release'
86
+ env:
87
+ GH_TOKEN: ${{ github.token }}
88
+ run: gh release upload "$GITHUB_REF_NAME" dist/Chronicle-*.dmg --clobber
89
+
90
+ - name: Keep DMG as a workflow artifact
91
+ if: github.event_name != 'release'
92
+ uses: actions/upload-artifact@v4
93
+ with:
94
+ name: Chronicle-dmg
95
+ path: dist/Chronicle-*.dmg
@@ -0,0 +1,7 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ .pytest_cache/
5
+ dist/
6
+ build/
7
+ *.egg-info/
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,337 @@
1
+ Metadata-Version: 2.5
2
+ Name: agents-chronicle
3
+ Version: 0.1.0
4
+ Summary: Record, archive, analyze and explore every coding-agent session (Claude Code, Codex, Copilot, Bob): a local knowledge vault built with Claude Code itself.
5
+ Project-URL: Repository, https://github.com/kayeungadrian-tam/agents-chronicle
6
+ Project-URL: Issues, https://github.com/kayeungadrian-tam/agents-chronicle/issues
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: rich>=13.7
9
+ Provides-Extra: app
10
+ Requires-Dist: pyobjc-framework-servicemanagement>=11; (sys_platform == 'darwin') and extra == 'app'
11
+ Requires-Dist: pywebview<7,>=6.2; (sys_platform == 'darwin') and extra == 'app'
12
+ Description-Content-Type: text/markdown
13
+
14
+ # Claude Chronicle
15
+
16
+ Records every coding-agent session on this machine (Claude Code, and when connected OpenAI Codex, GitHub
17
+ Copilot and IBM Bob) into a local vault, keeps the raw transcripts forever, and uses Claude Code itself (headless
18
+ `claude -p`) to turn each session into an overview plus reusable knowledge. Browse everything in a local dashboard,
19
+ an Obsidian-compatible Markdown vault, the CLI, or from inside the agents themselves through an MCP server.
20
+
21
+ ![How Chronicle works: sources, archive, parse, SQLite, analysis with claude -p, knowledge, and the dashboard, vault, CLI and MCP server](docs/diagrams/architecture.excalidraw.svg)
22
+
23
+ ## Why
24
+
25
+ - **Claude Code deletes transcripts after 30 days** (`cleanupPeriodDays`). Chronicle mirrors every
26
+ file under `~/.claude/projects` into `~/.claude-chronicle/archive` (JSONL gzip-compressed) and never
27
+ deletes it. Sessions whose transcripts were already gone are partially recovered from
28
+ `~/.claude/history.jsonl` (prompts only, marked *history*).
29
+ - **Knowledge evaporates.** Fixes, gotchas, decisions and project facts discovered in a session are
30
+ extracted, deduplicated per project, and made searchable, including by Claude itself in later sessions.
31
+
32
+ ## Install
33
+
34
+ Chronicle runs on macOS and needs a logged-in [Claude Code](https://claude.com/claude-code) (`claude`), which
35
+ does the analysis. There are two ways to run it; both use the same data in `~/.claude-chronicle` and can coexist.
36
+
37
+ ### Desktop app
38
+
39
+ 1. Download `Chronicle-<version>-arm64.dmg` from the
40
+ [latest release](https://github.com/kayeungadrian-tam/agents-chronicle/releases/latest) (Apple silicon, macOS 13+).
41
+ 2. Open it and drag **Chronicle** into **Applications**, then open it from there.
42
+ 3. On first launch, choose **Connect** to record Claude Code sessions. This adds the `SessionEnd` hook and the MCP
43
+ server (as `chronicle connect claude` does) and makes Chronicle open at login.
44
+
45
+ If macOS says Chronicle "cannot be opened" or "cannot verify the developer", that release was not notarized:
46
+ open **System Settings → Privacy & Security**, click **Open Anyway** next to the Chronicle message, and confirm.
47
+ There is no Intel build yet; on an Intel Mac use the command line install.
48
+
49
+ Chronicle then lives in the menu bar. It serves the dashboard in its own window and does the 15-minute
50
+ background sync itself, so it needs no launchd agents; closing the window keeps it running. The menu-bar icon has:
51
+
52
+ | Menu item | |
53
+ | --- | --- |
54
+ | Open Chronicle / Open in Browser | The dashboard, in the app window or your browser |
55
+ | Sync Now | Archive, ingest and analyze now instead of at the next 15-minute run; the line above it shows the last sync |
56
+ | Connect Claude Code… | Shown until Claude Code is connected (if you chose *Not Now* at first launch) |
57
+ | Open at Login | On after connecting; turn it off to run Chronicle only when you open it |
58
+ | Install Command-Line Tool | Links the app's own `chronicle` command into `~/.local/bin` (skipped if one exists) |
59
+ | Open Data Folder | `~/.claude-chronicle` |
60
+
61
+ Codex, Copilot and Bob are connected from the dashboard's **Sources** page. Hooks and MCP registrations point
62
+ at `~/.claude-chronicle/bin/chronicle`, a small script the app rewrites on every launch, so moving or updating the
63
+ app does not break them. Quitting stops the sync until the next launch; an analysis cut off by quitting runs
64
+ again at the next sync.
65
+
66
+ Known issues when the app is used without a command-line install:
67
+
68
+ - The dashboard's **Status** and **Sources** pages and `chronicle status` show *Background sync* as not running,
69
+ because they only check the launchd agent. The app's own sync is running; the menu-bar menu shows when it
70
+ last ran.
71
+ - `analysis.backfill = false` has no effect: the app's Connect step does not record the install date that
72
+ `chronicle install` records, so sessions from before connecting are analyzed too. To apply the setting, run
73
+ `~/.claude-chronicle/bin/chronicle install --no-launchd --no-ui` once, which records the date and reinstalls
74
+ the hook and MCP server.
75
+
76
+ To remove Chronicle, run `~/.claude-chronicle/bin/chronicle uninstall` (hooks and MCP
77
+ servers; data is kept), turn off **Open at Login**, and delete the app.
78
+
79
+ ### Command line
80
+
81
+ ```bash
82
+ uv tool install --python 3.13 agents-chronicle # puts `chronicle` on PATH (~/.local/bin)
83
+ chronicle sync # archive + ingest everything now
84
+ chronicle install # hooks, background agents, MCP server
85
+ chronicle connect codex # optional: codex, copilot, bob (see Sources)
86
+ ```
87
+
88
+ Needs [uv](https://docs.astral.sh/uv/) (or `pipx install agents-chronicle`). To install from a checkout instead,
89
+ run `uv tool install --python 3.13 .` in it. `chronicle install` does four things (each can be skipped with
90
+ `--no-hooks`, `--no-launchd`, `--no-ui`, `--no-mcp`; preview with `--dry-run`):
91
+
92
+ | Piece | What it does |
93
+ | --- | --- |
94
+ | `SessionEnd` hook in `~/.claude/settings.json` | Hands the ended transcript to a detached process that archives, ingests and analyzes it. Returns in milliseconds; a backup of `settings.json` is kept in `~/.claude-chronicle/backups/`. |
95
+ | launchd `com.claude-chronicle.sync` | `chronicle sync --work` every 15 minutes: catches anything the hook missed, processes the analysis queue, synthesizes knowledge bases, exports notes. |
96
+ | launchd `com.claude-chronicle.ui` | Keeps the dashboard at <http://127.0.0.1:8765/>. |
97
+ | MCP server `chronicle` (user scope) | Lets Claude Code search your past sessions and knowledge. |
98
+
99
+ Optional: `chronicle install --inject-context` also adds a `SessionStart` hook that gives each new
100
+ session a short digest of the project's knowledge base (off by default; preview it with `chronicle context`).
101
+
102
+ Remove everything with `chronicle uninstall` (data is kept; `--purge` deletes it too).
103
+
104
+ To use the desktop app from a command-line install, add the `app` extra and run `chronicle app`:
105
+ `uv tool install --python 3.13 'agents-chronicle[app]'`. If you switch to the app for good, `chronicle uninstall`
106
+ first and let the app connect Claude Code, so the launchd agents do not run alongside it (harmless, but redundant).
107
+
108
+ ## Sources: Claude Code, Codex, GitHub Copilot, IBM Bob
109
+
110
+ `chronicle sources` (or the dashboard's **Sources** tab) shows each coding agent: detected or not, version,
111
+ sessions on disk vs. recorded and analyzed, how it is recorded, and whether its hook and MCP server are in
112
+ place. Connect or disconnect from the dashboard or with `chronicle connect <agent>` / `chronicle disconnect <agent>`
113
+ (`claude`, `codex`, `copilot`, `bob`; recorded sessions are always kept). Every source maps onto the same session
114
+ model, so sessions from all agents share the dashboard, analysis, knowledge bases, glossary and MCP tools.
115
+
116
+ **Codex** (`~/.codex`) is opt-in. Connecting it:
117
+
118
+ - records `sources.codex_dirs` in the config, archives `~/.codex/sessions` (rollouts), `session_index.jsonl`
119
+ and Codex's own memory notes, and parses rollouts into the same session model: prompts (the IDE-context
120
+ envelope is unwrapped), replies, tool calls (`exec_command`, `apply_patch`, `write_stdin`, web, MCP, subagents;
121
+ a code-mode `exec` script is named after the tool it calls), file edits (`FileChange` items or patches), real
122
+ exit codes (result chunks, `CommandExecution` items, and long-running cells finished by `wait`), token usage
123
+ per response, compactions and interrupts;
124
+ - registers the MCP server in Codex (`codex mcp add chronicle`), so Codex can search every session, Claude's too;
125
+ - **recovers Claude Code sessions** that Codex Desktop imported: when Claude Code has already deleted the
126
+ original transcript, Codex's copy becomes a full session (`source = codex-import`); duplicates are skipped.
127
+
128
+ Codex has no session-end hook (and its single `notify` slot may be taken by another app), so Codex sessions
129
+ are picked up by the 15-minute background sync once idle. GPT token costs use OpenAI list prices; newer GPT
130
+ models without a published price are estimated at GPT-5 rates.
131
+
132
+ **GitHub Copilot** is opt-in (`chronicle connect copilot`). It records two stores:
133
+
134
+ - Copilot agent sessions in `~/.copilot/session-state/<id>/events.jsonl` (Copilot CLI and VS Code's Copilot
135
+ agent host): prompts, replies, reasoning, tool calls with results and durations, and line totals. Token usage
136
+ per call (with cache splits) comes from `~/.copilot/session-store.db`, archived as a SQLite snapshot.
137
+ - Copilot Chat in VS Code: `User/workspaceStorage/<hash>/chatSessions/*.jsonl`. Each file is a patch log that is
138
+ replayed into the final chat. The agent loop gives tool calls, results and edits; empty chat panels are skipped.
139
+ These logs do not split cached input from uncached input, so they carry token counts but no cost estimate.
140
+
141
+ Connecting also registers the MCP server in VS Code (`User/mcp.json`) and the Copilot CLI (`~/.copilot/mcp-config.json`).
142
+ Both files are backed up to `~/.claude-chronicle/backups/` first, and other servers in them are kept.
143
+
144
+ **IBM Bob** is opt-in (`chronicle connect bob`). It reads tasks and messages from `~/.bob/db/bob.db`, read-only,
145
+ and archives a SQLite snapshot of that database; nothing else in `~/.bob` (e.g. login state) is read. The Bob IDE
146
+ keeps no conversation files locally, so only the tasks in that database are recorded. Connecting registers the MCP
147
+ server in `~/.bob/settings/mcp_settings.json`.
148
+
149
+ ## Using it
150
+
151
+ | Command | |
152
+ | --- | --- |
153
+ | `chronicle app` | The desktop app (window + menu bar); needs the `app` extra |
154
+ | `chronicle ui [--open]` | Dashboard (also always running at :8765 after install). Sessions, Knowledge, Projects and Glossary switch between Cards and List (a sortable table; click a row for details), remembered per page |
155
+ | `chronicle sessions [-p project] [--since 7d]` | List sessions |
156
+ | `chronicle show <id-prefix> [--transcript\|--markdown\|--json]` | Session overview or full conversation |
157
+ | `chronicle search <words>` | Full-text search over transcripts + knowledge (any language, 3+ chars) |
158
+ | `chronicle knowledge [query] [-k gotcha] [-p project]` | Browse extracted knowledge |
159
+ | `chronicle projects` / `chronicle stats [--since 30d]` | Per-project and overall statistics |
160
+ | `chronicle analyze <id> \| --pending [--limit N] [--dry-run]` | Analyze now (`--dry-run` shows digest sizes, no tokens spent) |
161
+ | `chronicle synthesize [--project P] [--global] [--all]` | Rebuild knowledge bases |
162
+ | `chronicle export [--full]` | Rewrite the Markdown vault |
163
+ | `chronicle glossary [term] [-p project] [--rebuild --all]` | Your vocabulary: internal names, acronyms, domain terms with definitions and usage |
164
+ | `chronicle review [2026-W39\|current]` | Weekly engineering review written by Claude (automatic for each completed week) |
165
+ | `chronicle forget <id> [--delete-transcript]` | Remove a session from the vault for good (it is never re-ingested) |
166
+ | `chronicle sources` | Which agents are connected, and how |
167
+ | `chronicle connect <agent>` / `disconnect <agent>` | Start/stop recording `claude`, `codex`, `copilot` or `bob` (data is kept) |
168
+ | `chronicle status` | Health: hooks, agents, MCP, queue, failures |
169
+ | `chronicle config [edit]` | Show or edit `~/.claude-chronicle/config.toml` |
170
+
171
+ **Dashboard:** overview (active-time headline with active days and longest run; stat tiles with sparklines and
172
+ a per-day rate until a full prior period exists to compare against; daily chart with a 7-day average; outcome
173
+ breakdown; activity calendar with streaks; busiest hour; projects, tools with failed calls, models and agents),
174
+ sortable/filterable session list, project cards with 12 weeks of activity, session pages (summary, knowledge,
175
+ context-window chart with compactions, tools, files, subagents, PRs, full transcript replay with
176
+ collapsible tool calls and subagent threads), knowledge browser (pin/dismiss), project knowledge
177
+ bases, global playbook, glossary, a mindmap of the glossary (see Map below), weekly reviews, search with
178
+ jump-to-message. Glossary terms are underlined
179
+ wherever they appear (transcripts, knowledge, summaries): hover for the definition, click for the entry.
180
+ Every chart has a table view; light and dark themes.
181
+
182
+ **Markdown vault:** `~/.claude-chronicle/notes` (open it as an Obsidian vault): `Home.md`,
183
+ `Sessions/YYYY/MM/*.md` with YAML frontmatter, `Projects/*.md` (knowledge base + session list),
184
+ `Knowledge/<Kind>.md`, `Reviews/YYYY-Www.md`, `Glossary.md`, `Global Playbook.md`.
185
+
186
+ **Inside your agents** (MCP tools, registered in Claude Code and in each connected agent): `search_knowledge`, `search_sessions`, `get_session`,
187
+ `get_transcript`, `project_knowledge`, `glossary`, `recent_sessions`. Ask e.g. *"have we hit this error before?"*
188
+ or *"what is the deployer_ip rule?"*.
189
+
190
+ **Glossary:** built by Claude from each project's distilled knowledge (not the raw transcripts), one call per
191
+ project plus a cross-project pass, refreshed whenever a project's knowledge base is re-synthesized. Each term has
192
+ a category, aliases (abbreviations, translations of Japanese business terms), a definition, a per-project usage
193
+ note, related terms, and full-text statistics: how many sessions mention it, first and last seen, top sessions.
194
+
195
+ **Map:** the dashboard's **Map** page draws the glossary as a collapsible mindmap, built from data Chronicle
196
+ already has (no extra Claude calls). **By category** goes from categories to terms; **By project** goes from
197
+ projects to their categories to terms, with *Everywhere* holding the cross-project terms. Click a node to open or
198
+ close it, and a term to see its definition, where each project uses it, related terms (click to jump there) and
199
+ the knowledge items it was distilled from. Drag or scroll to move, pinch or ⌘-scroll to zoom; **Find a term**
200
+ opens the path to it, and the view glides to keep an opened branch on screen. Colour marks the category (the eight
201
+ largest have their own hue, the rest share grey); a term's dot grows with the number of sessions that mention it
202
+ (1, 2–4, 5+). With nothing selected, the side panel lists the terms shared by the most projects and the most
203
+ discussed ones. File
204
+ names and commands are hidden until you turn on **Files & commands**, no branch draws more than 10 children
205
+ (12 at the top): the most-discussed come first, and *+N more* lists the rest in the side panel, filterable as you
206
+ type, where picking one adds just that node to the map (search and related-term links do the same). Every glossary entry links to its place on the map (*on the map →*).
207
+
208
+ ## What gets recorded
209
+
210
+ Per session: project, branch, Claude Code version, start/end, wall and active time (idle gaps over
211
+ 15 min excluded), human prompts (including ones queued while Claude worked), slash commands,
212
+ interrupts, compactions, every tool call with duration and success, files read/edited with
213
+ line counts, subagents and workflows with their own usage, skills, MCP servers, hooks, PRs and
214
+ artifacts, and token usage per API call (deduplicated per message) with an API-list-price cost
215
+ estimate. Estimates match Claude Code's own `cost-state` to the cent for single-process sessions;
216
+ subscription billing differs.
217
+
218
+ Per analyzed session: title, summary, goal, outcome, work types, tags, highlights, open threads,
219
+ friction, sentiment, and knowledge items:
220
+
221
+ | Kind | Meaning |
222
+ | --- | --- |
223
+ | fix | a failure, its root cause, and the fix |
224
+ | gotcha | a pitfall and how to avoid it |
225
+ | learning | an insight about a technology or the codebase |
226
+ | decision | a design choice and its rationale |
227
+ | pattern | a reusable technique or snippet |
228
+ | command | a useful invocation |
229
+ | fact | project layout, config, endpoints, deployment |
230
+ | preference | how you want Claude to work |
231
+ | reference | an external pointer |
232
+ | todo | a follow-up |
233
+
234
+ Claude's own auto-memory notes (`projects/*/memory/*.md`) and Codex's memory notes are imported as knowledge too.
235
+
236
+ Codex, Copilot and Bob sessions fill the same fields wherever their logs carry the data: Copilot Chat logs, for
237
+ instance, have no cache split (so no cost estimate), and Bob tasks have no per-call timings.
238
+
239
+ ## How analysis works
240
+
241
+ ![How a session becomes knowledge: queue, digest, claude -p, JSON validation, knowledge items, knowledge bases, glossary and weekly review](docs/diagrams/analysis.excalidraw.svg)
242
+
243
+ 1. A session is queued once it ends (hook) or has been idle for `idle_minutes`.
244
+ 2. The transcript is condensed into a digest at the richest detail level that fits `chunk_chars`
245
+ (full prompts and replies, one line per tool call, error excerpts, subagent reports). Very long
246
+ sessions are split at prompt boundaries and map-reduced. Secrets are redacted first.
247
+ 3. `claude -p` runs with `--no-session-persistence --safe-mode --tools "" --strict-mcp-config`:
248
+ no transcript is written for the analysis itself, no hooks/plugins/MCP load, and the model can only answer.
249
+ `CHRONICLE_INTERNAL=1` makes the hooks inert for these runs.
250
+ 4. The JSON reply is validated leniently (with one repair pass) and stored. When a project gains
251
+ `min_new_items` new items, its knowledge base is re-synthesized; items that are outdated or
252
+ duplicated get marked *superseded* (pinned and memory items are never superseded). Once every session of
253
+ a finished week is analyzed, Claude writes that week's review (themes, accomplishments, learnings, open
254
+ threads, recurring friction, concrete workflow suggestions).
255
+ 5. Usage-limit or auth errors pause analysis for an hour; other failures back off 30 min → 2 h → 8 h.
256
+ Calls have a wall-clock deadline, and a call frozen by the Mac going to sleep is killed right after wake and
257
+ re-queued without counting as a failure. Sessions that continue after being analyzed are re-analyzed.
258
+
259
+ Cost: analysis runs through your Claude Code login. The reported cost is the API list-price equivalent: sessions
260
+ averaged about $0.38 each with Sonnet (digests average ~150k characters). On a Claude subscription that is drawn
261
+ from the plan's usage allowance rather than billed. `chronicle analyze --pending --dry-run` sizes a backlog, and
262
+ `max_budget_usd` caps each call.
263
+
264
+ ## Configuration (`~/.claude-chronicle/config.toml`)
265
+
266
+ | Key | Default | |
267
+ | --- | --- | --- |
268
+ | `sources.claude_dirs` | `["~/.claude"]` | multiple Claude config dirs are supported |
269
+ | `sources.codex_dirs` | `[]` | `["~/.codex"]` once Codex is connected |
270
+ | `sources.copilot_dirs` | `[]` | `~/.copilot` and VS Code `User` dirs once Copilot is connected |
271
+ | `sources.bob_dirs` | `[]` | `["~/.bob"]` once Bob is connected |
272
+ | `sources.exclude_projects` | `[]` | glob patterns of project paths to ignore entirely |
273
+ | `analysis.auto` | `true` | analyze automatically |
274
+ | `analysis.model` / `effort` | `sonnet` / `medium` | any `claude --model` alias |
275
+ | `analysis.max_per_run` / `concurrency` | `6` / `2` | throttle per 15-minute run |
276
+ | `analysis.backfill` | `true` | also analyze sessions recorded before install |
277
+ | `analysis.idle_minutes` | `20` | |
278
+ | `synthesis.auto` / `min_new_items` | `true` / `3` | |
279
+ | `export.markdown` / `notes_dir` | `true` / `~/.claude-chronicle/notes` | |
280
+ | `server.port` | `8765` | the app uses a free port instead when this one is taken (e.g. by the launchd dashboard) |
281
+ | `inject.session_start` | `false` | knowledge digest in new sessions |
282
+
283
+ `CHRONICLE_HOME` relocates everything.
284
+
285
+ ## Data & privacy
286
+
287
+ Everything stays on this machine: `~/.claude-chronicle/{chronicle.db, archive/, notes/, logs/}` (the app adds
288
+ `bin/chronicle`, the launcher its hooks call, and `webview/`, its window's storage).
289
+ The only thing sent anywhere is the redacted digest, sent to Claude through your own Claude Code
290
+ installation (the same service that produced the transcript). The dashboard binds to 127.0.0.1,
291
+ rejects foreign `Host` headers (DNS rebinding) and requires a custom header on state-changing requests (CSRF).
292
+ Other agents' stores are only read (SQLite databases through read-only connections and archived as snapshots);
293
+ Bob's login state is never read. Connecting an agent edits its MCP config, backed up to
294
+ `~/.claude-chronicle/backups/` first.
295
+
296
+ ## Development
297
+
298
+ ```bash
299
+ uv sync && uv run pytest -q # 83 tests, ~10 s: a fake `claude` binary and synthetic Codex, Copilot and Bob stores
300
+ # redeploy: --reinstall is required, uv caches local builds keyed on pyproject.toml only
301
+ uv tool install --force --reinstall --python 3.13 . && chronicle install # install restarts the agents
302
+ ```
303
+
304
+ **macOS app:** `uv run --extra app chronicle app` runs it from the checkout (menu-bar actions that only make sense
305
+ in the bundle, such as Open at Login, are hidden). `./packaging/macos/build.sh` builds `dist/Chronicle.app` and
306
+ `dist/Chronicle-<version>-<arch>.dmg` (PyInstaller, ~30 s; `packaging/macos/Chronicle.spec`). One binary is both the
307
+ app (no arguments) and the CLI (any arguments), which is how hooks and MCP servers run it. Unsigned builds are ad-hoc
308
+ signed and run on the Mac that built them; to distribute, set `CHRONICLE_CODESIGN_IDENTITY` (a Developer ID
309
+ Application certificate) and `NOTARY_KEYCHAIN_PROFILE` (from `xcrun notarytool store-credentials`), and the script
310
+ signs, notarizes and staples the DMG. `packaging/macos/make_icon.py` redraws the icon. `desktop.py` extends
311
+ pywebview's Cocoa app delegate, hence the `<7` pin on pywebview.
312
+
313
+ **Releasing:** bump `version` in `pyproject.toml`, then publish a GitHub release tagged `v<version>`.
314
+ `.github/workflows/release.yml` runs the tests, publishes `agents-chronicle` to PyPI (trusted publishing,
315
+ environment `pypi`) and attaches the DMG to the release (signed and notarized when the `MACOS_*` / `APPLE_*`
316
+ secrets are set; see the workflow header). Running the workflow by hand (**Actions → Release → Run workflow**)
317
+ is a dry run: tests plus a DMG kept as a workflow artifact, nothing published.
318
+
319
+ One-time setup before the first release:
320
+
321
+ 1. On PyPI, add a *pending publisher* (Account → Publishing): project `agents-chronicle`, owner
322
+ `kayeungadrian-tam`, repository `agents-chronicle`, workflow `release.yml`, environment `pypi`.
323
+ 2. In the GitHub repository, create an environment named `pypi` (Settings → Environments).
324
+ 3. To ship a signed, notarized DMG (Apple Developer Program membership): export the *Developer ID Application*
325
+ certificate with its key as a `.p12`, and add the secrets `MACOS_CERT_P12` (base64 of the file),
326
+ `MACOS_CERT_PASSWORD`, `MACOS_CODESIGN_IDENTITY`, `APPLE_ID`, `APPLE_TEAM_ID` and `APPLE_APP_PASSWORD`
327
+ (an app-specific password from account.apple.com). Without them the DMG is ad-hoc signed and users have to
328
+ approve it in Privacy & Security.
329
+
330
+ Diagrams in `docs/diagrams/` are `.excalidraw.svg` files: they render as images and open for editing in the
331
+ Excalidraw VS Code extension (`pomdtr.excalidraw-editor`) or on excalidraw.com; saving writes back to the same file.
332
+
333
+ Layout: `parser.py` (Claude transcript format), `codex_parser.py` (Codex rollouts), `copilot_parser.py` (Copilot agent
334
+ sessions + VS Code chat logs), `bob_parser.py` (Bob tasks), `agents.py` (agent names), `connectors.py` (Sources),
335
+ `ingest.py` (archive + store), `digest.py` / `analyze.py` /
336
+ `llm.py` (analysis), `synthesize.py` (knowledge bases), `glossary.py`, `reviews.py`, `worker.py` (queue), `server.py` + `web/`
337
+ (dashboard), `mcp_server.py`, `export_md.py`, `hooks.py` / `install.py`, `desktop.py` (macOS app), `cli.py`; `packaging/macos/` builds the app.