ccrecall 0.10.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.
- ccrecall-0.10.0/LICENSE +21 -0
- ccrecall-0.10.0/PKG-INFO +244 -0
- ccrecall-0.10.0/README.md +210 -0
- ccrecall-0.10.0/pyproject.toml +113 -0
- ccrecall-0.10.0/setup.cfg +4 -0
- ccrecall-0.10.0/src/ccrecall/__init__.py +18 -0
- ccrecall-0.10.0/src/ccrecall/cli/__init__.py +98 -0
- ccrecall-0.10.0/src/ccrecall/cli/commands.py +245 -0
- ccrecall-0.10.0/src/ccrecall/cli/context.py +31 -0
- ccrecall-0.10.0/src/ccrecall/content.py +152 -0
- ccrecall-0.10.0/src/ccrecall/db.py +306 -0
- ccrecall-0.10.0/src/ccrecall/embeddings.py +125 -0
- ccrecall-0.10.0/src/ccrecall/formatting.py +144 -0
- ccrecall-0.10.0/src/ccrecall/fusion.py +17 -0
- ccrecall-0.10.0/src/ccrecall/hooks/__init__.py +0 -0
- ccrecall-0.10.0/src/ccrecall/hooks/backfill_embeddings.py +374 -0
- ccrecall-0.10.0/src/ccrecall/hooks/backfill_summaries.py +99 -0
- ccrecall-0.10.0/src/ccrecall/hooks/clear_handoff.py +49 -0
- ccrecall-0.10.0/src/ccrecall/hooks/import_conversations.py +271 -0
- ccrecall-0.10.0/src/ccrecall/hooks/memory_context.py +539 -0
- ccrecall-0.10.0/src/ccrecall/hooks/memory_setup.py +162 -0
- ccrecall-0.10.0/src/ccrecall/hooks/memory_sync.py +57 -0
- ccrecall-0.10.0/src/ccrecall/hooks/onboarding.py +83 -0
- ccrecall-0.10.0/src/ccrecall/hooks/sync_current.py +154 -0
- ccrecall-0.10.0/src/ccrecall/hooks/write_config.py +51 -0
- ccrecall-0.10.0/src/ccrecall/models.py +121 -0
- ccrecall-0.10.0/src/ccrecall/parsing.py +314 -0
- ccrecall-0.10.0/src/ccrecall/project_ops.py +92 -0
- ccrecall-0.10.0/src/ccrecall/recent_chats.py +204 -0
- ccrecall-0.10.0/src/ccrecall/schema.py +192 -0
- ccrecall-0.10.0/src/ccrecall/search_conversations.py +500 -0
- ccrecall-0.10.0/src/ccrecall/serialization.py +41 -0
- ccrecall-0.10.0/src/ccrecall/session_ops.py +563 -0
- ccrecall-0.10.0/src/ccrecall/session_tail.py +384 -0
- ccrecall-0.10.0/src/ccrecall/summarizer.py +427 -0
- ccrecall-0.10.0/src/ccrecall/token_analytics.py +212 -0
- ccrecall-0.10.0/src/ccrecall/token_dashboard.py +119 -0
- ccrecall-0.10.0/src/ccrecall/token_insights.py +862 -0
- ccrecall-0.10.0/src/ccrecall/token_output.py +867 -0
- ccrecall-0.10.0/src/ccrecall/token_parser.py +661 -0
- ccrecall-0.10.0/src/ccrecall/token_schema.py +206 -0
- ccrecall-0.10.0/src/ccrecall.egg-info/PKG-INFO +244 -0
- ccrecall-0.10.0/src/ccrecall.egg-info/SOURCES.txt +73 -0
- ccrecall-0.10.0/src/ccrecall.egg-info/dependency_links.txt +1 -0
- ccrecall-0.10.0/src/ccrecall.egg-info/entry_points.txt +7 -0
- ccrecall-0.10.0/src/ccrecall.egg-info/requires.txt +11 -0
- ccrecall-0.10.0/src/ccrecall.egg-info/top_level.txt +1 -0
- ccrecall-0.10.0/tests/test_backfill_embeddings.py +719 -0
- ccrecall-0.10.0/tests/test_boundary_validation.py +149 -0
- ccrecall-0.10.0/tests/test_clear_handoff_contract.py +233 -0
- ccrecall-0.10.0/tests/test_cli_context.py +23 -0
- ccrecall-0.10.0/tests/test_content.py +377 -0
- ccrecall-0.10.0/tests/test_context_injection.py +738 -0
- ccrecall-0.10.0/tests/test_db.py +826 -0
- ccrecall-0.10.0/tests/test_embeddings.py +110 -0
- ccrecall-0.10.0/tests/test_formatting.py +283 -0
- ccrecall-0.10.0/tests/test_fusion.py +62 -0
- ccrecall-0.10.0/tests/test_import_pipeline.py +699 -0
- ccrecall-0.10.0/tests/test_ingest_token_data.py +620 -0
- ccrecall-0.10.0/tests/test_integration.py +267 -0
- ccrecall-0.10.0/tests/test_onboarding.py +164 -0
- ccrecall-0.10.0/tests/test_parsing.py +383 -0
- ccrecall-0.10.0/tests/test_project_ops.py +132 -0
- ccrecall-0.10.0/tests/test_recent_chats.py +158 -0
- ccrecall-0.10.0/tests/test_search.py +909 -0
- ccrecall-0.10.0/tests/test_security.py +92 -0
- ccrecall-0.10.0/tests/test_serialization.py +58 -0
- ccrecall-0.10.0/tests/test_session_ops.py +690 -0
- ccrecall-0.10.0/tests/test_session_tail.py +276 -0
- ccrecall-0.10.0/tests/test_summarizer.py +667 -0
- ccrecall-0.10.0/tests/test_sync_hook.py +641 -0
- ccrecall-0.10.0/tests/test_token_insights.py +530 -0
- ccrecall-0.10.0/tests/test_token_output.py +211 -0
- ccrecall-0.10.0/tests/test_token_parser.py +280 -0
- ccrecall-0.10.0/tests/test_write_config.py +186 -0
ccrecall-0.10.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jessica Smith
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
ccrecall-0.10.0/PKG-INFO
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ccrecall
|
|
3
|
+
Version: 0.10.0
|
|
4
|
+
Summary: Conversation history and semantic search for Claude Code
|
|
5
|
+
Author-email: Jessica Smith <12jessicasmith34@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/NodeJSmith/claude-code-recall
|
|
8
|
+
Project-URL: Issues, https://github.com/NodeJSmith/claude-code-recall/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/NodeJSmith/claude-code-recall/blob/main/CHANGELOG.md
|
|
10
|
+
Keywords: claude-code,conversation-history,search,recall,transcripts,semantic-search
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Topic :: Utilities
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: sqlite-vec==0.1.9
|
|
27
|
+
Requires-Dist: fastembed==0.8.0
|
|
28
|
+
Requires-Dist: numpy==2.2.6; python_version < "3.11"
|
|
29
|
+
Requires-Dist: numpy==2.4.6; python_version >= "3.11"
|
|
30
|
+
Requires-Dist: whenever==0.10.0
|
|
31
|
+
Requires-Dist: pydantic==2.13.4
|
|
32
|
+
Requires-Dist: cyclopts>=4.16
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# ccrecall
|
|
36
|
+
|
|
37
|
+
**Conversation history and semantic search for Claude Code.**
|
|
38
|
+
|
|
39
|
+
ccrecall stores your Claude Code sessions in a local SQLite database so you can recall past conversations, search across them by keyword and meaning, and get automatic context on session start. Everything runs on your machine — no data leaves it.
|
|
40
|
+
|
|
41
|
+
> ccrecall is an independent, community project for [Claude Code](https://docs.anthropic.com/en/docs/claude-code). It is not affiliated with, endorsed by, or sponsored by Anthropic.
|
|
42
|
+
|
|
43
|
+
## What it does
|
|
44
|
+
|
|
45
|
+
Every time a Claude Code session ends, the conversation is synced to `~/.ccrecall/conversations.db`. On your next session start, Claude automatically gets a summary of what you were last working on. You can also search past sessions by keyword or pull recent ones at any time.
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
ccrecall has two parts: a **Python package** (the `ccrecall` CLI plus the hook binaries) and a **Claude Code plugin** (the `/ccr-*` skills and the hook wiring). Install both.
|
|
50
|
+
|
|
51
|
+
**1. Install the package** — puts `ccrecall` and the hook commands on your PATH:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
uv tool install ccrecall
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
(`pipx install ccrecall` or `pip install ccrecall` work too.)
|
|
58
|
+
|
|
59
|
+
**2. Enable the plugin** — ccrecall ships as a Claude Code plugin. The repo doubles as a single-plugin marketplace, so from inside Claude Code:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
/plugin marketplace add NodeJSmith/claude-code-recall
|
|
63
|
+
/plugin install ccrecall@claude-code-recall
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
That registers the skills and wires the SessionStart / Stop / SessionEnd hooks (`hooks/hooks.json`) — both are auto-discovered from the plugin's directory layout. Reload with `/reload-plugins` if they don't appear immediately.
|
|
67
|
+
|
|
68
|
+
> Plugin skills are namespaced under the plugin name, so the skills below are invoked as `/ccrecall:ccr-recall`, `/ccrecall:ccr-resume`, and `/ccrecall:ccr-tokens`. The hook commands degrade gracefully — each is guarded by `command -v … || true`, so if the package isn't installed (or isn't yet on PATH) the hook is a silent no-op rather than a broken session.
|
|
69
|
+
|
|
70
|
+
## First-run setup
|
|
71
|
+
|
|
72
|
+
On your first session after installing, Claude will notice that `~/.ccrecall/config.json` doesn't exist and walk you through a brief onboarding. It asks a single question — **session context injection**: should Claude automatically recall what you were working on last session?
|
|
73
|
+
|
|
74
|
+
Your choice gets written to `~/.ccrecall/config.json`. You can edit that file directly at any time to change settings.
|
|
75
|
+
|
|
76
|
+
To skip the walkthrough and use recommended defaults immediately:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
ccrecall write-config --defaults
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Semantic search
|
|
83
|
+
|
|
84
|
+
Search results are fused from two signals: keyword full-text search (FTS5 → FTS4 → LIKE fallback) and vector similarity from a locally-running embedding model. The two ranked lists are merged with Reciprocal Rank Fusion (RRF), so results that rank well in both signals appear first.
|
|
85
|
+
|
|
86
|
+
The embedding model is [jina-embeddings-v2-small-en](https://huggingface.co/jinaai/jina-embeddings-v2-small-en) (512-dim), running entirely on your machine via [fastembed](https://github.com/qdrant/fastembed). No data leaves your machine.
|
|
87
|
+
|
|
88
|
+
### Coverage
|
|
89
|
+
|
|
90
|
+
New sessions are embedded automatically as they sync (embed-on-write), so coverage builds forward on its own. Only **active-leaf** branches are embedded — at most one active leaf per session (maintained by sync/import), not its abandoned forks/retries. The flag isn't DB-enforced, but sync/import marks exactly one branch `is_active=1` per session. The search path only ever returns active leaves, so embedding inactive forks would just produce vectors that can never surface.
|
|
91
|
+
|
|
92
|
+
### Optional: seed historical conversations
|
|
93
|
+
|
|
94
|
+
Embedding runs on CPU via fastembed. jina-v2-small-en is light — a few milliseconds for a short summary, up to ~400ms for a long one — but seeding a large history (~2k active leaves) is still a bounded chunk of work, and a parallel run can thrash a small or shared box. It is therefore **opt-in** — it is *not* auto-spawned on SessionStart — so it never fires unbidden. Run it yourself when you want to seed:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
ccrecall backfill embeddings # all active leaves, all history
|
|
98
|
+
ccrecall backfill embeddings --days 14 # only the last 14 days
|
|
99
|
+
ccrecall backfill embeddings --limit 500 # cap this run at 500 branches
|
|
100
|
+
ccrecall backfill embeddings --threads 4 # use 4 inference threads (idle machine)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
It runs at low scheduling priority (`nice`) and a single inference thread by default so it yields to interactive work. Tune the thread count with `--threads` (e.g. `--threads 4` on an idle workstation to finish faster). Progress prints to stderr (one line per batch); the run is resumable — re-running skips already-embedded branches.
|
|
104
|
+
|
|
105
|
+
### Flags
|
|
106
|
+
|
|
107
|
+
| Flag | Effect |
|
|
108
|
+
|------|--------|
|
|
109
|
+
| `--keyword-only` | Skip the embedding step entirely, use keyword search only |
|
|
110
|
+
| `--status` | Print diagnostic info (vec extension loaded, model name, embedded vs. total summarized (embeddable) branch count) and exit 0 |
|
|
111
|
+
|
|
112
|
+
### Runtime deps
|
|
113
|
+
|
|
114
|
+
The semantic search path requires three extra packages beyond the base install:
|
|
115
|
+
|
|
116
|
+
- `sqlite-vec` — SQLite extension for vector KNN queries
|
|
117
|
+
- `fastembed` — downloads and runs the embedding model (manages onnxruntime + tokenization)
|
|
118
|
+
- `numpy` — vector math (normalization)
|
|
119
|
+
|
|
120
|
+
These are included in the package dependencies. If fastembed fails to import (e.g. ABI mismatch on an unusual platform), search falls back silently to keyword-only mode.
|
|
121
|
+
|
|
122
|
+
### Degradation
|
|
123
|
+
|
|
124
|
+
Semantic fusion is automatically disabled when:
|
|
125
|
+
- The embedding model can't be loaded (e.g. a first-run download failed and no cached copy exists)
|
|
126
|
+
- `fastembed` cannot be imported
|
|
127
|
+
- `sqlite-vec` cannot be loaded on the connection (e.g. Python built without loadable extensions)
|
|
128
|
+
|
|
129
|
+
In all cases, search falls back to keyword-only and returns results normally. Use `ccrecall search --status` to check which path is active.
|
|
130
|
+
|
|
131
|
+
## Skills
|
|
132
|
+
|
|
133
|
+
| Skill | Trigger | What it does |
|
|
134
|
+
|---|---|---|
|
|
135
|
+
| `/ccr-recall` | "what did we discuss", "continue where we left off", "search my conversations" | Lets Claude search or browse your past sessions on demand |
|
|
136
|
+
| `/ccr-resume` | "pick up where we left off after /clear", a stop, or an unanswered question | Reconstructs the prior session's intent from its transcript tail and surfaces any unresolved decision |
|
|
137
|
+
| `/ccr-tokens` | "analyze Claude token usage", "how much am I spending on Claude" | Full cost + workflow analytics report with an interactive HTML dashboard |
|
|
138
|
+
|
|
139
|
+
## Entry points
|
|
140
|
+
|
|
141
|
+
### Hooks (run automatically — don't call these manually)
|
|
142
|
+
|
|
143
|
+
These are wired by the plugin's `hooks/hooks.json` and fire on their respective Claude Code events.
|
|
144
|
+
|
|
145
|
+
| Entry point | Event | What it does |
|
|
146
|
+
|---|---|---|
|
|
147
|
+
| `ccrecall-setup` | SessionStart | Creates `~/.ccrecall/` if needed, opens the DB to apply any pending migrations, then spawns `ccrecall import` and `ccrecall backfill summaries` as background processes |
|
|
148
|
+
| `ccrecall-onboarding` | SessionStart (startup only) | One-time first-run onboarding. Injects setup instructions into Claude's context if `config.json` is missing or onboarding hasn't been completed. Silent no-op after that |
|
|
149
|
+
| `ccrecall-context` | SessionStart (startup + clear) | Injects a summary of your most recent session into Claude's context so it knows what you were working on. On `/clear`, reads a handoff file to link directly to the session you just cleared from |
|
|
150
|
+
| `ccrecall-clear-handoff` | SessionEnd (clear only) | Writes a small handoff file so the next session start knows which session to link to after a `/clear`. Without this, context injection falls back to a "most recent session" heuristic |
|
|
151
|
+
| `ccrecall-sync` | Stop | Syncs the current session to the DB in a detached background process. Runs on every session end |
|
|
152
|
+
|
|
153
|
+
> These are kept as separate console scripts (rather than `ccrecall hook …` subcommands) on purpose: hooks fire on every session boundary, and a direct entry point avoids eagerly importing the full CLI command surface on the hot path.
|
|
154
|
+
|
|
155
|
+
### Internal helpers (spawned by hooks — don't call these manually)
|
|
156
|
+
|
|
157
|
+
| Entry point | What it does |
|
|
158
|
+
|---|---|
|
|
159
|
+
| `ccrecall sync-current` | Syncs a single session file to the DB. Called by `ccrecall-sync` with the session ID from stdin |
|
|
160
|
+
| `ccrecall import` | Full import of all JSONL files in `~/.claude/projects/`. Skips files that haven't changed since last import (file hash check). Run on first install and whenever new sessions need backfilling |
|
|
161
|
+
| `ccrecall backfill summaries` | Generates context summaries for any DB branches that don't have one yet. Runs in the background after `ccrecall-setup` |
|
|
162
|
+
| `ccrecall write-config` | Writes `~/.ccrecall/config.json`. Called by Claude during onboarding to persist your settings choices. You can also call it directly — run `ccrecall write-config --help` for flags |
|
|
163
|
+
|
|
164
|
+
### Skill CLIs (called from skill files — can also be used directly)
|
|
165
|
+
|
|
166
|
+
These are the `ccrecall` subcommands the `/ccr-*` skills invoke. You can run them from the terminal too.
|
|
167
|
+
|
|
168
|
+
| Entry point | What it does |
|
|
169
|
+
|---|---|
|
|
170
|
+
| `ccrecall recent` | Prints recent sessions from the DB in markdown (default) or JSON. Used by `/ccr-recall` |
|
|
171
|
+
| `ccrecall search` | Searches sessions by keyword fused with vector similarity (FTS5 → FTS4 → LIKE fallback, RRF-fused with jina embeddings when available). Used by `/ccr-recall` |
|
|
172
|
+
| `ccrecall tail` | Reads the tail of a prior session's transcript to recover the last instruction and any unanswered question. Used by `/ccr-resume` |
|
|
173
|
+
| `ccrecall backfill embeddings` | Opt-in seeding of embeddings for historical active-leaf branches (jina-v2-small-en via fastembed). Not auto-spawned. Supports `--days N` / `--limit N` / `--threads N`; throttled via `nice` + a single inference thread by default. Resumable |
|
|
174
|
+
| `ccrecall tokens` | Parses JSONL files for token usage analytics — cost, cache hits, model mix, skill/agent/hook patterns. Populates analytics tables and builds `~/.ccrecall/dashboard.html`. Used by `/ccr-tokens` |
|
|
175
|
+
|
|
176
|
+
## Data flow
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
Session ends
|
|
180
|
+
└─ ccrecall-sync (Stop hook)
|
|
181
|
+
└─ ccrecall sync-current (background)
|
|
182
|
+
└─ writes to ~/.ccrecall/conversations.db
|
|
183
|
+
└─ embeds the active leaf via jina if model available (drops silently on failure)
|
|
184
|
+
|
|
185
|
+
/clear (SessionEnd)
|
|
186
|
+
└─ ccrecall-clear-handoff
|
|
187
|
+
└─ writes a handoff file naming the session being cleared
|
|
188
|
+
(so the next SessionStart links to it instead of guessing)
|
|
189
|
+
|
|
190
|
+
Session starts
|
|
191
|
+
└─ ccrecall-setup (SessionStart)
|
|
192
|
+
│ └─ ccrecall import (background, first run / new files)
|
|
193
|
+
│ └─ embeds each new active leaf via jina if model available
|
|
194
|
+
│ └─ ccrecall backfill summaries (background, if summaries missing)
|
|
195
|
+
│ └─ (embedding backfill is NOT auto-spawned — opt-in via ccrecall backfill embeddings)
|
|
196
|
+
├─ ccrecall-onboarding (SessionStart, startup only — one-time)
|
|
197
|
+
└─ ccrecall-context (SessionStart, startup + clear)
|
|
198
|
+
└─ injects last session summary into Claude's context
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Config file
|
|
202
|
+
|
|
203
|
+
`~/.ccrecall/config.json` — written by `ccrecall write-config` during onboarding:
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
{
|
|
207
|
+
"onboarding_completed": true,
|
|
208
|
+
"onboarding_version": 1,
|
|
209
|
+
"auto_inject_context": true
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Onboarding sets `auto_inject_context`. The remaining settings are tunable by editing `config.json` directly:
|
|
214
|
+
|
|
215
|
+
| Key | Type | Default | Effect |
|
|
216
|
+
|---|---|---|---|
|
|
217
|
+
| `auto_inject_context` | bool | `true` | Inject a summary of your previous session at session start. |
|
|
218
|
+
| `max_context_sessions` | int | `2` | How many recent sessions to include in that injected context. |
|
|
219
|
+
| `exclude_projects` | list[str] | `[]` | Project names to skip when **storing** conversations — excluded projects are not imported or synced. Matched against the project's directory name. This is write-side only: it prevents new data from being indexed; it does not remove or hide conversations already stored before the project was excluded. |
|
|
220
|
+
| `logging_enabled` | bool | `false` | Write hook diagnostics (including swallowed hook exceptions) to `~/.ccrecall/ccrecall.log`. Useful for troubleshooting a misbehaving hook. |
|
|
221
|
+
|
|
222
|
+
## Database
|
|
223
|
+
|
|
224
|
+
`~/.ccrecall/conversations.db` — SQLite, WAL mode. Tables:
|
|
225
|
+
|
|
226
|
+
- `sessions` — one row per conversation session
|
|
227
|
+
- `branches` — one row per conversation branch (rewinding creates new branches)
|
|
228
|
+
- `messages` — all messages, stored once per session regardless of branch
|
|
229
|
+
- `branch_messages` — join table linking messages to branches
|
|
230
|
+
- `import_log` — tracks which JSONL files have been imported and their hashes
|
|
231
|
+
- `branch_vec` — vec0 virtual table (sqlite-vec) storing 512-dim jina embeddings for each branch, used for KNN search
|
|
232
|
+
- `token_snapshots`, `turns`, `turn_tool_calls`, `session_metrics` — analytics tables populated by `ccrecall tokens`
|
|
233
|
+
|
|
234
|
+
## Development
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
uv sync # install package + dev dependencies
|
|
238
|
+
uv run pytest # run the test suite
|
|
239
|
+
uvx prek run --all-files # run the lint/format/type hooks
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## License
|
|
243
|
+
|
|
244
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# ccrecall
|
|
2
|
+
|
|
3
|
+
**Conversation history and semantic search for Claude Code.**
|
|
4
|
+
|
|
5
|
+
ccrecall stores your Claude Code sessions in a local SQLite database so you can recall past conversations, search across them by keyword and meaning, and get automatic context on session start. Everything runs on your machine — no data leaves it.
|
|
6
|
+
|
|
7
|
+
> ccrecall is an independent, community project for [Claude Code](https://docs.anthropic.com/en/docs/claude-code). It is not affiliated with, endorsed by, or sponsored by Anthropic.
|
|
8
|
+
|
|
9
|
+
## What it does
|
|
10
|
+
|
|
11
|
+
Every time a Claude Code session ends, the conversation is synced to `~/.ccrecall/conversations.db`. On your next session start, Claude automatically gets a summary of what you were last working on. You can also search past sessions by keyword or pull recent ones at any time.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
ccrecall has two parts: a **Python package** (the `ccrecall` CLI plus the hook binaries) and a **Claude Code plugin** (the `/ccr-*` skills and the hook wiring). Install both.
|
|
16
|
+
|
|
17
|
+
**1. Install the package** — puts `ccrecall` and the hook commands on your PATH:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
uv tool install ccrecall
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
(`pipx install ccrecall` or `pip install ccrecall` work too.)
|
|
24
|
+
|
|
25
|
+
**2. Enable the plugin** — ccrecall ships as a Claude Code plugin. The repo doubles as a single-plugin marketplace, so from inside Claude Code:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
/plugin marketplace add NodeJSmith/claude-code-recall
|
|
29
|
+
/plugin install ccrecall@claude-code-recall
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
That registers the skills and wires the SessionStart / Stop / SessionEnd hooks (`hooks/hooks.json`) — both are auto-discovered from the plugin's directory layout. Reload with `/reload-plugins` if they don't appear immediately.
|
|
33
|
+
|
|
34
|
+
> Plugin skills are namespaced under the plugin name, so the skills below are invoked as `/ccrecall:ccr-recall`, `/ccrecall:ccr-resume`, and `/ccrecall:ccr-tokens`. The hook commands degrade gracefully — each is guarded by `command -v … || true`, so if the package isn't installed (or isn't yet on PATH) the hook is a silent no-op rather than a broken session.
|
|
35
|
+
|
|
36
|
+
## First-run setup
|
|
37
|
+
|
|
38
|
+
On your first session after installing, Claude will notice that `~/.ccrecall/config.json` doesn't exist and walk you through a brief onboarding. It asks a single question — **session context injection**: should Claude automatically recall what you were working on last session?
|
|
39
|
+
|
|
40
|
+
Your choice gets written to `~/.ccrecall/config.json`. You can edit that file directly at any time to change settings.
|
|
41
|
+
|
|
42
|
+
To skip the walkthrough and use recommended defaults immediately:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
ccrecall write-config --defaults
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Semantic search
|
|
49
|
+
|
|
50
|
+
Search results are fused from two signals: keyword full-text search (FTS5 → FTS4 → LIKE fallback) and vector similarity from a locally-running embedding model. The two ranked lists are merged with Reciprocal Rank Fusion (RRF), so results that rank well in both signals appear first.
|
|
51
|
+
|
|
52
|
+
The embedding model is [jina-embeddings-v2-small-en](https://huggingface.co/jinaai/jina-embeddings-v2-small-en) (512-dim), running entirely on your machine via [fastembed](https://github.com/qdrant/fastembed). No data leaves your machine.
|
|
53
|
+
|
|
54
|
+
### Coverage
|
|
55
|
+
|
|
56
|
+
New sessions are embedded automatically as they sync (embed-on-write), so coverage builds forward on its own. Only **active-leaf** branches are embedded — at most one active leaf per session (maintained by sync/import), not its abandoned forks/retries. The flag isn't DB-enforced, but sync/import marks exactly one branch `is_active=1` per session. The search path only ever returns active leaves, so embedding inactive forks would just produce vectors that can never surface.
|
|
57
|
+
|
|
58
|
+
### Optional: seed historical conversations
|
|
59
|
+
|
|
60
|
+
Embedding runs on CPU via fastembed. jina-v2-small-en is light — a few milliseconds for a short summary, up to ~400ms for a long one — but seeding a large history (~2k active leaves) is still a bounded chunk of work, and a parallel run can thrash a small or shared box. It is therefore **opt-in** — it is *not* auto-spawned on SessionStart — so it never fires unbidden. Run it yourself when you want to seed:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
ccrecall backfill embeddings # all active leaves, all history
|
|
64
|
+
ccrecall backfill embeddings --days 14 # only the last 14 days
|
|
65
|
+
ccrecall backfill embeddings --limit 500 # cap this run at 500 branches
|
|
66
|
+
ccrecall backfill embeddings --threads 4 # use 4 inference threads (idle machine)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
It runs at low scheduling priority (`nice`) and a single inference thread by default so it yields to interactive work. Tune the thread count with `--threads` (e.g. `--threads 4` on an idle workstation to finish faster). Progress prints to stderr (one line per batch); the run is resumable — re-running skips already-embedded branches.
|
|
70
|
+
|
|
71
|
+
### Flags
|
|
72
|
+
|
|
73
|
+
| Flag | Effect |
|
|
74
|
+
|------|--------|
|
|
75
|
+
| `--keyword-only` | Skip the embedding step entirely, use keyword search only |
|
|
76
|
+
| `--status` | Print diagnostic info (vec extension loaded, model name, embedded vs. total summarized (embeddable) branch count) and exit 0 |
|
|
77
|
+
|
|
78
|
+
### Runtime deps
|
|
79
|
+
|
|
80
|
+
The semantic search path requires three extra packages beyond the base install:
|
|
81
|
+
|
|
82
|
+
- `sqlite-vec` — SQLite extension for vector KNN queries
|
|
83
|
+
- `fastembed` — downloads and runs the embedding model (manages onnxruntime + tokenization)
|
|
84
|
+
- `numpy` — vector math (normalization)
|
|
85
|
+
|
|
86
|
+
These are included in the package dependencies. If fastembed fails to import (e.g. ABI mismatch on an unusual platform), search falls back silently to keyword-only mode.
|
|
87
|
+
|
|
88
|
+
### Degradation
|
|
89
|
+
|
|
90
|
+
Semantic fusion is automatically disabled when:
|
|
91
|
+
- The embedding model can't be loaded (e.g. a first-run download failed and no cached copy exists)
|
|
92
|
+
- `fastembed` cannot be imported
|
|
93
|
+
- `sqlite-vec` cannot be loaded on the connection (e.g. Python built without loadable extensions)
|
|
94
|
+
|
|
95
|
+
In all cases, search falls back to keyword-only and returns results normally. Use `ccrecall search --status` to check which path is active.
|
|
96
|
+
|
|
97
|
+
## Skills
|
|
98
|
+
|
|
99
|
+
| Skill | Trigger | What it does |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| `/ccr-recall` | "what did we discuss", "continue where we left off", "search my conversations" | Lets Claude search or browse your past sessions on demand |
|
|
102
|
+
| `/ccr-resume` | "pick up where we left off after /clear", a stop, or an unanswered question | Reconstructs the prior session's intent from its transcript tail and surfaces any unresolved decision |
|
|
103
|
+
| `/ccr-tokens` | "analyze Claude token usage", "how much am I spending on Claude" | Full cost + workflow analytics report with an interactive HTML dashboard |
|
|
104
|
+
|
|
105
|
+
## Entry points
|
|
106
|
+
|
|
107
|
+
### Hooks (run automatically — don't call these manually)
|
|
108
|
+
|
|
109
|
+
These are wired by the plugin's `hooks/hooks.json` and fire on their respective Claude Code events.
|
|
110
|
+
|
|
111
|
+
| Entry point | Event | What it does |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| `ccrecall-setup` | SessionStart | Creates `~/.ccrecall/` if needed, opens the DB to apply any pending migrations, then spawns `ccrecall import` and `ccrecall backfill summaries` as background processes |
|
|
114
|
+
| `ccrecall-onboarding` | SessionStart (startup only) | One-time first-run onboarding. Injects setup instructions into Claude's context if `config.json` is missing or onboarding hasn't been completed. Silent no-op after that |
|
|
115
|
+
| `ccrecall-context` | SessionStart (startup + clear) | Injects a summary of your most recent session into Claude's context so it knows what you were working on. On `/clear`, reads a handoff file to link directly to the session you just cleared from |
|
|
116
|
+
| `ccrecall-clear-handoff` | SessionEnd (clear only) | Writes a small handoff file so the next session start knows which session to link to after a `/clear`. Without this, context injection falls back to a "most recent session" heuristic |
|
|
117
|
+
| `ccrecall-sync` | Stop | Syncs the current session to the DB in a detached background process. Runs on every session end |
|
|
118
|
+
|
|
119
|
+
> These are kept as separate console scripts (rather than `ccrecall hook …` subcommands) on purpose: hooks fire on every session boundary, and a direct entry point avoids eagerly importing the full CLI command surface on the hot path.
|
|
120
|
+
|
|
121
|
+
### Internal helpers (spawned by hooks — don't call these manually)
|
|
122
|
+
|
|
123
|
+
| Entry point | What it does |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `ccrecall sync-current` | Syncs a single session file to the DB. Called by `ccrecall-sync` with the session ID from stdin |
|
|
126
|
+
| `ccrecall import` | Full import of all JSONL files in `~/.claude/projects/`. Skips files that haven't changed since last import (file hash check). Run on first install and whenever new sessions need backfilling |
|
|
127
|
+
| `ccrecall backfill summaries` | Generates context summaries for any DB branches that don't have one yet. Runs in the background after `ccrecall-setup` |
|
|
128
|
+
| `ccrecall write-config` | Writes `~/.ccrecall/config.json`. Called by Claude during onboarding to persist your settings choices. You can also call it directly — run `ccrecall write-config --help` for flags |
|
|
129
|
+
|
|
130
|
+
### Skill CLIs (called from skill files — can also be used directly)
|
|
131
|
+
|
|
132
|
+
These are the `ccrecall` subcommands the `/ccr-*` skills invoke. You can run them from the terminal too.
|
|
133
|
+
|
|
134
|
+
| Entry point | What it does |
|
|
135
|
+
|---|---|
|
|
136
|
+
| `ccrecall recent` | Prints recent sessions from the DB in markdown (default) or JSON. Used by `/ccr-recall` |
|
|
137
|
+
| `ccrecall search` | Searches sessions by keyword fused with vector similarity (FTS5 → FTS4 → LIKE fallback, RRF-fused with jina embeddings when available). Used by `/ccr-recall` |
|
|
138
|
+
| `ccrecall tail` | Reads the tail of a prior session's transcript to recover the last instruction and any unanswered question. Used by `/ccr-resume` |
|
|
139
|
+
| `ccrecall backfill embeddings` | Opt-in seeding of embeddings for historical active-leaf branches (jina-v2-small-en via fastembed). Not auto-spawned. Supports `--days N` / `--limit N` / `--threads N`; throttled via `nice` + a single inference thread by default. Resumable |
|
|
140
|
+
| `ccrecall tokens` | Parses JSONL files for token usage analytics — cost, cache hits, model mix, skill/agent/hook patterns. Populates analytics tables and builds `~/.ccrecall/dashboard.html`. Used by `/ccr-tokens` |
|
|
141
|
+
|
|
142
|
+
## Data flow
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
Session ends
|
|
146
|
+
└─ ccrecall-sync (Stop hook)
|
|
147
|
+
└─ ccrecall sync-current (background)
|
|
148
|
+
└─ writes to ~/.ccrecall/conversations.db
|
|
149
|
+
└─ embeds the active leaf via jina if model available (drops silently on failure)
|
|
150
|
+
|
|
151
|
+
/clear (SessionEnd)
|
|
152
|
+
└─ ccrecall-clear-handoff
|
|
153
|
+
└─ writes a handoff file naming the session being cleared
|
|
154
|
+
(so the next SessionStart links to it instead of guessing)
|
|
155
|
+
|
|
156
|
+
Session starts
|
|
157
|
+
└─ ccrecall-setup (SessionStart)
|
|
158
|
+
│ └─ ccrecall import (background, first run / new files)
|
|
159
|
+
│ └─ embeds each new active leaf via jina if model available
|
|
160
|
+
│ └─ ccrecall backfill summaries (background, if summaries missing)
|
|
161
|
+
│ └─ (embedding backfill is NOT auto-spawned — opt-in via ccrecall backfill embeddings)
|
|
162
|
+
├─ ccrecall-onboarding (SessionStart, startup only — one-time)
|
|
163
|
+
└─ ccrecall-context (SessionStart, startup + clear)
|
|
164
|
+
└─ injects last session summary into Claude's context
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Config file
|
|
168
|
+
|
|
169
|
+
`~/.ccrecall/config.json` — written by `ccrecall write-config` during onboarding:
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"onboarding_completed": true,
|
|
174
|
+
"onboarding_version": 1,
|
|
175
|
+
"auto_inject_context": true
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Onboarding sets `auto_inject_context`. The remaining settings are tunable by editing `config.json` directly:
|
|
180
|
+
|
|
181
|
+
| Key | Type | Default | Effect |
|
|
182
|
+
|---|---|---|---|
|
|
183
|
+
| `auto_inject_context` | bool | `true` | Inject a summary of your previous session at session start. |
|
|
184
|
+
| `max_context_sessions` | int | `2` | How many recent sessions to include in that injected context. |
|
|
185
|
+
| `exclude_projects` | list[str] | `[]` | Project names to skip when **storing** conversations — excluded projects are not imported or synced. Matched against the project's directory name. This is write-side only: it prevents new data from being indexed; it does not remove or hide conversations already stored before the project was excluded. |
|
|
186
|
+
| `logging_enabled` | bool | `false` | Write hook diagnostics (including swallowed hook exceptions) to `~/.ccrecall/ccrecall.log`. Useful for troubleshooting a misbehaving hook. |
|
|
187
|
+
|
|
188
|
+
## Database
|
|
189
|
+
|
|
190
|
+
`~/.ccrecall/conversations.db` — SQLite, WAL mode. Tables:
|
|
191
|
+
|
|
192
|
+
- `sessions` — one row per conversation session
|
|
193
|
+
- `branches` — one row per conversation branch (rewinding creates new branches)
|
|
194
|
+
- `messages` — all messages, stored once per session regardless of branch
|
|
195
|
+
- `branch_messages` — join table linking messages to branches
|
|
196
|
+
- `import_log` — tracks which JSONL files have been imported and their hashes
|
|
197
|
+
- `branch_vec` — vec0 virtual table (sqlite-vec) storing 512-dim jina embeddings for each branch, used for KNN search
|
|
198
|
+
- `token_snapshots`, `turns`, `turn_tool_calls`, `session_metrics` — analytics tables populated by `ccrecall tokens`
|
|
199
|
+
|
|
200
|
+
## Development
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
uv sync # install package + dev dependencies
|
|
204
|
+
uv run pytest # run the test suite
|
|
205
|
+
uvx prek run --all-files # run the lint/format/type hooks
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=80", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ccrecall"
|
|
7
|
+
version = "0.10.0"
|
|
8
|
+
description = "Conversation history and semantic search for Claude Code"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Jessica Smith", email = "12jessicasmith34@gmail.com" }]
|
|
14
|
+
keywords = [
|
|
15
|
+
"claude-code",
|
|
16
|
+
"conversation-history",
|
|
17
|
+
"search",
|
|
18
|
+
"recall",
|
|
19
|
+
"transcripts",
|
|
20
|
+
"semantic-search",
|
|
21
|
+
]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Development Status :: 4 - Beta",
|
|
24
|
+
"Environment :: Console",
|
|
25
|
+
"Intended Audience :: Developers",
|
|
26
|
+
"Operating System :: OS Independent",
|
|
27
|
+
"Programming Language :: Python :: 3",
|
|
28
|
+
"Programming Language :: Python :: 3.10",
|
|
29
|
+
"Programming Language :: Python :: 3.11",
|
|
30
|
+
"Programming Language :: Python :: 3.12",
|
|
31
|
+
"Programming Language :: Python :: 3.13",
|
|
32
|
+
"Programming Language :: Python :: 3.14",
|
|
33
|
+
"Topic :: Utilities",
|
|
34
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
35
|
+
]
|
|
36
|
+
# Pinned to the versions in uv.lock: `uv tool install` without a lockfile
|
|
37
|
+
# ignores uv.lock and resolves fresh, so an unbounded range would pull newer
|
|
38
|
+
# ABI/runtime-breaking releases of these native wheels.
|
|
39
|
+
# fastembed is the embedding engine — it owns the ONNX runtime + tokenizers and
|
|
40
|
+
# the model download, so onnxruntime is left to fastembed's own constraint (an
|
|
41
|
+
# explicit pin here fights its resolver) and reproducibility comes from uv.lock.
|
|
42
|
+
# numpy is a direct dependency and uses Python-version markers. To re-sync after
|
|
43
|
+
# a bump: `uv lock` then mirror the resolved versions here.
|
|
44
|
+
dependencies = [
|
|
45
|
+
"sqlite-vec==0.1.9",
|
|
46
|
+
"fastembed==0.8.0",
|
|
47
|
+
"numpy==2.2.6; python_version < '3.11'",
|
|
48
|
+
"numpy==2.4.6; python_version >= '3.11'",
|
|
49
|
+
"whenever==0.10.0",
|
|
50
|
+
# Pin pydantic exactly so its native (Rust) pydantic-core dep resolves to a
|
|
51
|
+
# known ABI — same rationale as the native wheels above.
|
|
52
|
+
"pydantic==2.13.4",
|
|
53
|
+
"cyclopts>=4.16",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[project.urls]
|
|
57
|
+
Homepage = "https://github.com/NodeJSmith/claude-code-recall"
|
|
58
|
+
Issues = "https://github.com/NodeJSmith/claude-code-recall/issues"
|
|
59
|
+
Changelog = "https://github.com/NodeJSmith/claude-code-recall/blob/main/CHANGELOG.md"
|
|
60
|
+
|
|
61
|
+
[project.scripts]
|
|
62
|
+
# Unified CLI — single entry point. Subcommands replace the former skill-facing
|
|
63
|
+
# and helper cm-* tools.
|
|
64
|
+
ccrecall = "ccrecall.cli:main"
|
|
65
|
+
# Hook entry points (wired by the plugin's hooks/hooks.json). Kept as separate
|
|
66
|
+
# console scripts rather than `ccrecall hook ...` subcommands on purpose: hooks
|
|
67
|
+
# fire on every SessionStart/Stop, and routing through the full cyclopts app
|
|
68
|
+
# eager-imports the whole command surface (fastembed/numpy/onnxruntime, ~1800ms)
|
|
69
|
+
# vs ~440ms for a direct hook import. The no-lazy-imports rule rules out dodging
|
|
70
|
+
# that, so a direct entry point per hook stays the fast path.
|
|
71
|
+
ccrecall-setup = "ccrecall.hooks.memory_setup:main"
|
|
72
|
+
ccrecall-sync = "ccrecall.hooks.memory_sync:main"
|
|
73
|
+
ccrecall-context = "ccrecall.hooks.memory_context:main"
|
|
74
|
+
ccrecall-onboarding = "ccrecall.hooks.onboarding:main"
|
|
75
|
+
ccrecall-clear-handoff = "ccrecall.hooks.clear_handoff:main"
|
|
76
|
+
|
|
77
|
+
[tool.setuptools.packages.find]
|
|
78
|
+
where = ["src"]
|
|
79
|
+
|
|
80
|
+
[dependency-groups]
|
|
81
|
+
dev = [
|
|
82
|
+
"pytest>=8.0",
|
|
83
|
+
"hypothesis>=6.0",
|
|
84
|
+
"pytest-cov>=7.0.0",
|
|
85
|
+
"coverage[toml]>=7.10.7",
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
[tool.pytest.ini_options]
|
|
89
|
+
testpaths = ["tests"]
|
|
90
|
+
|
|
91
|
+
[tool.coverage.run]
|
|
92
|
+
branch = true # measure branch coverage, not just lines
|
|
93
|
+
source = ["ccrecall"]
|
|
94
|
+
parallel = true # suffix data files so per-Python-version CI shards combine cleanly
|
|
95
|
+
relative_files = true # stable paths across CI runners
|
|
96
|
+
omit = ["*/__init__.py", "*/__main__.py"]
|
|
97
|
+
|
|
98
|
+
[tool.coverage.report]
|
|
99
|
+
show_missing = true
|
|
100
|
+
skip_covered = true
|
|
101
|
+
# fail_under = 80 # enable once a baseline is established; CI can override
|
|
102
|
+
exclude_lines = [
|
|
103
|
+
"pragma: no cover",
|
|
104
|
+
"if TYPE_CHECKING:",
|
|
105
|
+
"if __name__ == .__main__.:",
|
|
106
|
+
"raise NotImplementedError",
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
[tool.coverage.html]
|
|
110
|
+
directory = "htmlcov"
|
|
111
|
+
|
|
112
|
+
[tool.coverage.xml]
|
|
113
|
+
output = "coverage.xml"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ccrecall — conversation memory package for Claude Code.
|
|
3
|
+
|
|
4
|
+
Submodules:
|
|
5
|
+
db — Database connection, config/settings, vec operations, logging
|
|
6
|
+
schema — Conversation DB schema constants (SCHEMA_*) and FTS detection
|
|
7
|
+
content — Message content extraction and tool detection
|
|
8
|
+
parsing — JSONL parsing, branch detection, metadata extraction
|
|
9
|
+
formatting — Session formatting, time/path utilities
|
|
10
|
+
project_ops — Shared project upsert logic (cwd strategy + JSONL-probe strategy)
|
|
11
|
+
session_ops — Shared session import logic (used by sync and import pipelines)
|
|
12
|
+
token_schema — Token ingest schema definitions, ensure_schema(), version management
|
|
13
|
+
token_parser — Token JSONL parsing, data classes, session parsing, file discovery
|
|
14
|
+
token_analytics — Session import and token_snapshots backfill
|
|
15
|
+
token_output — Dashboard JSON output assembly (chart queries)
|
|
16
|
+
token_insights — Trend analysis, insight generation, findings/recommendations
|
|
17
|
+
token_dashboard — Token dashboard deployment and main() entry point
|
|
18
|
+
"""
|