sift-cc 0.2.1__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.
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "monthly"
@@ -0,0 +1,37 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ name: Lint (ruff)
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - name: Install ruff
19
+ run: pip install ruff
20
+ - name: Ruff check
21
+ run: ruff check .
22
+
23
+ test:
24
+ name: Test (Python ${{ matrix.python-version }} / ${{ matrix.os }})
25
+ runs-on: ${{ matrix.os }}
26
+ strategy:
27
+ fail-fast: false
28
+ matrix:
29
+ os: [ubuntu-latest, macos-latest]
30
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
31
+ steps:
32
+ - uses: actions/checkout@v4
33
+ - uses: actions/setup-python@v5
34
+ with:
35
+ python-version: ${{ matrix.python-version }}
36
+ - name: Run tests
37
+ run: python -m unittest discover -s tests -v
@@ -0,0 +1,40 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ jobs:
8
+ build:
9
+ name: Build distributions
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: "3.12"
16
+ - name: Install build
17
+ run: pip install build
18
+ - name: Build wheel and sdist
19
+ run: python -m build
20
+ - name: Upload artifacts
21
+ uses: actions/upload-artifact@v4
22
+ with:
23
+ name: dist
24
+ path: dist/
25
+
26
+ publish:
27
+ name: Publish to PyPI
28
+ needs: build
29
+ runs-on: ubuntu-latest
30
+ environment: pypi
31
+ permissions:
32
+ id-token: write
33
+ steps:
34
+ - name: Download artifacts
35
+ uses: actions/download-artifact@v4
36
+ with:
37
+ name: dist
38
+ path: dist/
39
+ - name: Publish to PyPI
40
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ build/
5
+ dist/
6
+ .venv*/
7
+ venv/
8
+ .env
9
+ .DS_Store
10
+ .pytest_cache/
11
+ .ruff_cache/
12
+ .mypy_cache/
13
+ .coverage
14
+ htmlcov/
15
+ sift-exports/
16
+ .claude/settings.local.json
@@ -0,0 +1,53 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.2.1] — 2026-05-30
9
+
10
+ ### Packaging
11
+ - Added GitHub Actions CI workflow: ruff lint plus unittest suite across Python 3.10–3.13 on Ubuntu and macOS.
12
+ - Added trusted-publishing release workflow that builds the wheel/sdist and publishes to PyPI on `v*` tags.
13
+ - Added minimal `[tool.ruff]` config (pyflakes + syntax errors only).
14
+ - Added Dependabot config to keep GitHub Actions versions current.
15
+
16
+ ## [0.2.0] — 2026-05-30
17
+
18
+ ### Added
19
+ - **Interactive TUI** — `sift` with no arguments launches a curses-based terminal UI: scrollable session list on the left, live preview pane on the right with stats, first prompt, and per-session tool/file activity bars. Live filter (`/`), full-archive content search (`s`), in-place actions for show / export / resume / copy-id / copy-path, help overlay (`?`), with a non-interactive `--help` fallback when not attached to a TTY. Uses `pbcopy` / `wl-copy` / `xclip` for clipboard, gracefully degrades when none are available.
20
+ - `sift last` — render the most recent session.
21
+ - `sift resume <id>` — print (or `--exec`) the `claude --resume` command for a session, in its original cwd.
22
+ - `sift files <id>` — list files touched by Read / Edit / Write / NotebookEdit / MultiEdit, with per-op breakdown.
23
+ - `sift tools <id>` — horizontal bar chart of tool usage in a session.
24
+ - `sift bash <id>` — extract every shell command run, with timestamps.
25
+ - `sift links <id>` — extract URLs, ranked by mention count and colored by source role.
26
+ - `sift export <id>` — clean markdown export with frontmatter, headings per turn, optional `<details>` thinking blocks, and tool-call summaries.
27
+ - `sift related <id>` — find similar sessions across the archive using TF-IDF cosine similarity.
28
+ - `sift pick` — interactive session picker using `fzf` when available, with numbered-menu fallback. Chained `--action show|path|resume|files|tools|id`.
29
+ - `sift prompts` — list first user prompts across recent sessions for quick "what was I working on?" recall.
30
+ - `sift completion bash|zsh|fish` — generate shell completion scripts with session-ID completion for relevant subcommands.
31
+ - `--version` flag.
32
+ - `--since` / `--until` accept relative spans (`7d`, `2w`, `12h`) or ISO dates on `list`, `search`, `stats`.
33
+ - `list --sort recent|tokens|messages|duration|input|output`.
34
+ - `search -l/--files-only` to print only matching session IDs.
35
+ - `stats` now includes per-session averages, standout sessions, an hour-of-day histogram, and an optional `--year` 52-week heatmap.
36
+ - `stats --json` for piping into other tools.
37
+ - `projects --json`.
38
+
39
+ ### Changed
40
+ - Numbers ≥ 1 G now formatted with a "G" suffix.
41
+ - Code-block extraction supports more language extensions (swift, kotlin, java, c/cpp, ruby, php, toml, scss, dockerfile, diff/patch, …).
42
+
43
+ ### Packaging
44
+ - Renamed `sift` → `sift.py` to enable `pip install`.
45
+ - Added `pyproject.toml` (hatchling) with `sift` console-script entry point.
46
+ - Added MIT `LICENSE`.
47
+
48
+ ## [0.1.0] — 2026-05-30
49
+
50
+ Initial release.
51
+
52
+ - `projects`, `list`, `search`, `show`, `code`, `stats`, `path`, `open`.
53
+ - Plain Python, stdlib only.
sift_cc-0.2.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Simon Mavec
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.
sift_cc-0.2.1/PKG-INFO ADDED
@@ -0,0 +1,316 @@
1
+ Metadata-Version: 2.4
2
+ Name: sift-cc
3
+ Version: 0.2.1
4
+ Summary: Mine your Claude Code conversation archive — search, browse, and extract from past sessions.
5
+ Project-URL: Homepage, https://github.com/SimonMav/sift-cc
6
+ Project-URL: Repository, https://github.com/SimonMav/sift-cc
7
+ Project-URL: Issues, https://github.com/SimonMav/sift-cc/issues
8
+ Author: Simon Mavec
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: archive,claude,claude-code,cli,conversations,search
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Software Development
24
+ Classifier: Topic :: Terminals
25
+ Classifier: Topic :: Utilities
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+
29
+ # sift
30
+
31
+ > Mine your Claude Code conversation archive.
32
+
33
+ Every Claude Code session you've ever had is sitting in `~/.claude/projects/` as a JSONL file. After a few weeks that archive becomes a goldmine: code you've already worked through, decisions you've already made, explanations you've already gotten — but there's no way to actually use it.
34
+
35
+ `sift` makes that archive usable. Open the interactive TUI, search across every conversation, browse sessions by project and time, extract code blocks, find related discussions, render whole sessions to markdown, and jump back into any one of them.
36
+
37
+ **Single Python file. Zero runtime dependencies. Pure stdlib.**
38
+
39
+ ```text
40
+ $ sift # interactive TUI (default when no args)
41
+
42
+ ▰ sift v0.2.1 · 145/145 sessions ? help q quit
43
+ press / to filter titles & paths · s to search conversation contents
44
+ ─────────────────────────────────────────────────────────────────────────────────
45
+ ▸ a1b2c3d webapp 173 just now Refactor auth middl… │ Refactor auth middleware
46
+ e4f5a6b notes 29 34m ago Add markdown table… │ a1b2c3d4-1111-2222-3333-444455556666
47
+ c7d8e9f cli-tool 58 1h ago Investigate slow s… │
48
+ 1a2b3c4 infra 35 1h ago Debug terraform pl… │ project ~/projects/webapp
49
+ 5d6e7f8 api-srv 48 3h ago Fix request timeou… │ branch main
50
+ 9a0b1c2 scratch 60 14h ago Sketch graph layou… │ started 2026-01-15 10:31
51
+ │ duration 1h22m
52
+ │ models claude-opus-4-7
53
+ │ messages 80 user, 143 assistant
54
+ │ tokens in 217 out 395.2k
55
+
56
+ │ top tools
57
+ │ Bash █████████████ 50
58
+ │ Write ████ 10
59
+ │ Edit ██ 7
60
+
61
+ ↑↓ nav / filter s search ⏎ show e export r resume c copy id ? help q quit
62
+ ```
63
+
64
+ …or use the underlying subcommands directly for scripting:
65
+
66
+ ```text
67
+ $ sift list --days 7
68
+ id project msgs last title
69
+ ────────────────────────────────────────────────────────────────────────────
70
+ a1b2c3d4 webapp 127 just now Refactor auth middleware
71
+ e4f5a6b7 notes 29 34m ago Add markdown table support
72
+ c7d8e9f0 cli-tool 58 1h ago Investigate slow startup
73
+ 1a2b3c4d infra 48 3h ago Fix terraform drift
74
+ 5d6e7f89 api-srv 60 14h ago Add request tracing
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Install
80
+
81
+ ### pip (recommended)
82
+
83
+ Until `sift` is published to PyPI, install from source:
84
+
85
+ ```sh
86
+ git clone https://github.com/SimonMav/sift-cc && cd sift
87
+ pip install .
88
+ ```
89
+
90
+ This puts `sift` on your `$PATH`.
91
+
92
+ ### Single file, no pip
93
+
94
+ ```sh
95
+ chmod +x sift.py
96
+ ln -s "$PWD/sift.py" /opt/homebrew/bin/sift # or anywhere on $PATH
97
+ ```
98
+
99
+ Requires **Python 3.10+** (uses `X | None` type syntax).
100
+
101
+ ### Shell completion
102
+
103
+ ```sh
104
+ sift completion bash >> ~/.bashrc
105
+ sift completion zsh > "${fpath[1]}/_sift"
106
+ sift completion fish > ~/.config/fish/completions/sift.fish
107
+ ```
108
+
109
+ ---
110
+
111
+ ## The TUI
112
+
113
+ Running `sift` with no arguments launches an interactive terminal UI. It opens a split view: scrollable session list on the left, live preview on the right with stats, the first prompt, and tool/file activity bars for the highlighted session.
114
+
115
+ Keybindings:
116
+
117
+ | Key | Action |
118
+ | --- | --- |
119
+ | `↑` `↓` / `k` `j` | Move cursor |
120
+ | `g` / `G` | Top / bottom |
121
+ | `PgUp` `PgDn` / `u` `d` | Page |
122
+ | `/` | Filter list (live — matches title, project, first prompt) |
123
+ | `s` | Search conversation **contents** across every session |
124
+ | `esc` | Clear the current filter or search |
125
+ | `⏎` | Render the selected session through your `$PAGER` |
126
+ | `e` | Export the session to `~/sift-exports/<id>-<slug>.md` |
127
+ | `r` | Copy `cd … && claude --resume …` to the clipboard |
128
+ | `c` | Copy session id |
129
+ | `p` | Copy session JSONL path |
130
+ | `R` | Reload sessions from disk |
131
+ | `?` | Help overlay |
132
+ | `q` | Quit |
133
+
134
+ Clipboard uses `pbcopy` on macOS, `wl-copy` or `xclip` on Linux. With no clipboard tool, the value is flashed in the footer instead.
135
+
136
+ If `sift` is invoked with no args in a non-interactive context (pipe, script), it prints `--help` instead of trying to start the TUI.
137
+
138
+ ## Commands
139
+
140
+ ### Browsing
141
+
142
+ | Command | What it does |
143
+ | --- | --- |
144
+ | `sift projects` | One-line summary per project — sessions, tokens, last activity. |
145
+ | `sift list` | Sessions across the archive, newest first. |
146
+ | `sift last` | Render the most recent session. |
147
+ | `sift pick` | Interactive picker (uses `fzf` if installed). |
148
+ | `sift prompts` | First user prompts across recent sessions — quick "what was I working on?". |
149
+
150
+ ### Single-session inspection
151
+
152
+ | Command | What it does |
153
+ | --- | --- |
154
+ | `sift show <id>` | Render a session readably (paged, colored, wrapped). |
155
+ | `sift files <id>` | Files touched (Read/Edit/Write), with per-op breakdown. |
156
+ | `sift tools <id>` | Tool-usage bar chart for the session. |
157
+ | `sift bash <id>` | Every shell command run, with timestamps. |
158
+ | `sift links <id>` | URLs mentioned, ranked by count, colored by source. |
159
+ | `sift code <id>` | Fenced code blocks. With `--out-dir`, writes each block to a file. |
160
+ | `sift export <id>` | Clean markdown export, optional `<details>` thinking blocks. |
161
+ | `sift path <id>` | Absolute path of the JSONL file. |
162
+ | `sift open <id>` | Open the JSONL in `$EDITOR`. |
163
+
164
+ ### Search and discovery
165
+
166
+ | Command | What it does |
167
+ | --- | --- |
168
+ | `sift search "q"` | Full-text search across every session. Regex, role filter, highlighting, context lines. |
169
+ | `sift related <id>` | Find similar sessions using TF-IDF cosine similarity. |
170
+
171
+ ### Analytics
172
+
173
+ | Command | What it does |
174
+ | --- | --- |
175
+ | `sift stats` | Token totals, model split, top projects, hour-of-day, 30-day strip. |
176
+ | `sift stats --year` | 52-week GitHub-style activity heatmap. |
177
+ | `sift stats --json` | Machine-readable summary for piping. |
178
+
179
+ ### Workflow
180
+
181
+ | Command | What it does |
182
+ | --- | --- |
183
+ | `sift resume <id>` | Print `claude --resume` in the session's original cwd. `--exec` runs it. |
184
+ | `sift completion {bash,zsh,fish}` | Generate a shell completion script. |
185
+
186
+ ---
187
+
188
+ ## Examples
189
+
190
+ ### Find that explanation from last month
191
+
192
+ ```sh
193
+ sift search "MVCC isolation" --user
194
+ sift search "rate limit" --assistant -C 2
195
+ sift search "fn .*\(unsafe" --regex
196
+ ```
197
+
198
+ ### Pick up where you left off
199
+
200
+ ```sh
201
+ sift last # render the most recent session
202
+ sift resume $(sift list --json --limit 1 | jq -r '.[0].session_id') --exec
203
+ ```
204
+
205
+ ### Cross-reference sessions
206
+
207
+ ```sh
208
+ sift related 003f1707 # find similar past work
209
+ sift related 003f1707 -p webapp # restrict to one project
210
+ ```
211
+
212
+ ### Export a session for sharing
213
+
214
+ ```sh
215
+ sift export 003f1707 -o write-up.md
216
+ sift export 003f1707 --thinking --tool-results -o full.md
217
+ ```
218
+
219
+ ### "What have I been working on?"
220
+
221
+ ```sh
222
+ sift prompts --days 14
223
+ sift stats --year
224
+ ```
225
+
226
+ ### Pipe into your own tools
227
+
228
+ ```sh
229
+ sift list --since 30d --json | jq '.[].title'
230
+ sift search "TODO" --files-only | xargs -I{} sift show {} --no-pager
231
+ sift code 003f1707 --lang python --out-dir ./extracted/
232
+ ```
233
+
234
+ ### Interactive flow with fzf
235
+
236
+ ```sh
237
+ sift pick # default action: show
238
+ sift pick --action resume # pick, then resume
239
+ sift pick -p webapp --since 7d # narrow the candidate set
240
+ ```
241
+
242
+ ---
243
+
244
+ ## Time filters
245
+
246
+ Anywhere `--since` or `--until` appears (and `--days` as a shorthand):
247
+
248
+ | Form | Meaning |
249
+ | --- | --- |
250
+ | `7d`, `2w`, `12h` | Relative offset from now. |
251
+ | `2026-05-01` | ISO date (UTC). |
252
+ | `2026-05-01T12:30:00` | ISO datetime. |
253
+
254
+ ```sh
255
+ sift list --since 7d
256
+ sift search "cache" --since 2026-05-01
257
+ sift stats --since 30d --until 2026-05-25
258
+ ```
259
+
260
+ ---
261
+
262
+ ## Session IDs
263
+
264
+ All commands that take a session accept either the full UUID or any **unique prefix**:
265
+
266
+ ```sh
267
+ sift show 003f1707 # ✓ if it's unique
268
+ sift show 003 # ✗ ambiguous — sift will list candidates
269
+ ```
270
+
271
+ `sift search` and `sift pick` are good ways to find an ID when you don't have one to hand.
272
+
273
+ ---
274
+
275
+ ## Environment
276
+
277
+ | Variable | Default | Purpose |
278
+ | --- | --- | --- |
279
+ | `SIFT_ARCHIVE` | `~/.claude/projects` | Where to look for session JSONLs. |
280
+ | `NO_COLOR` / `SIFT_NO_COLOR` | unset | Disable ANSI colors. |
281
+ | `EDITOR` | `vi` | Used by `sift open`. |
282
+ | `PAGER` | `less -RFX` | Used by `sift show` and `sift last` when stdout is a TTY. |
283
+
284
+ ---
285
+
286
+ ## Development
287
+
288
+ ```sh
289
+ git clone <repo> && cd sift
290
+ python3 -m pytest tests/ # 41 tests, runs in ~0.1s
291
+ python3 sift.py --version
292
+ ```
293
+
294
+ The project is a single file (`sift.py`) plus tests. Tests build a synthetic archive in a temp directory and exercise every subcommand — no fixtures committed to the repo, no external state.
295
+
296
+ ---
297
+
298
+ ## How it works
299
+
300
+ Claude Code writes one JSONL per session under `~/.claude/projects/<project>/<session-id>.jsonl`. Each line is a record: `user` and `assistant` messages, `ai-title` (Claude Code auto-titles sessions), `system`, `attachment`, etc.
301
+
302
+ `sift` parses these records lazily, builds summaries on demand, and ships nothing to any server. Everything is local.
303
+
304
+ The TF-IDF in `sift related` boosts the auto-title heavily (it's the highest-signal text in the corpus), reads ~30 KB of conversation per session, tokenizes on word characters minus a small English stopword set, and ranks by cosine similarity over IDF-weighted vectors. On a 145-session archive this takes under a second.
305
+
306
+ ---
307
+
308
+ ## License
309
+
310
+ MIT. See [LICENSE](LICENSE).
311
+
312
+ ---
313
+
314
+ ## Why
315
+
316
+ The conversations are right there. There just wasn't a good way to use them.