scrollback 0.1.0__py3-none-any.whl

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 (69) hide show
  1. scrollback/__init__.py +8 -0
  2. scrollback/assets/icon-256.png +0 -0
  3. scrollback/assets/icon.icns +0 -0
  4. scrollback/cli.py +1139 -0
  5. scrollback/clipboard.py +34 -0
  6. scrollback/export.py +293 -0
  7. scrollback/fts.py +307 -0
  8. scrollback/highlight.py +128 -0
  9. scrollback/katexbundle.py +81 -0
  10. scrollback/launcher_install.py +209 -0
  11. scrollback/launchers/scrollback.bat +19 -0
  12. scrollback/launchers/scrollback.command +19 -0
  13. scrollback/launchers/scrollback.desktop +10 -0
  14. scrollback/launchers/scrollback.sh +12 -0
  15. scrollback/mathspan.py +180 -0
  16. scrollback/minimd.py +205 -0
  17. scrollback/models.py +135 -0
  18. scrollback/serialize.py +83 -0
  19. scrollback/serverconfig.py +66 -0
  20. scrollback/sources/__init__.py +6 -0
  21. scrollback/sources/aider.py +244 -0
  22. scrollback/sources/base.py +117 -0
  23. scrollback/sources/claudecode.py +631 -0
  24. scrollback/sources/codex.py +281 -0
  25. scrollback/sources/opencode.py +357 -0
  26. scrollback/sources/registry.py +39 -0
  27. scrollback/store.py +384 -0
  28. scrollback/termrender.py +170 -0
  29. scrollback/web/__init__.py +1 -0
  30. scrollback/web/app.py +359 -0
  31. scrollback/web/static/app.js +1245 -0
  32. scrollback/web/static/apple-touch-icon.png +0 -0
  33. scrollback/web/static/favicon.png +0 -0
  34. scrollback/web/static/favicon.svg +41 -0
  35. scrollback/web/static/index.html +75 -0
  36. scrollback/web/static/style.css +628 -0
  37. scrollback/web/static/vendor/highlight.min.js +1213 -0
  38. scrollback/web/static/vendor/hljs-dark.min.css +10 -0
  39. scrollback/web/static/vendor/hljs-light.min.css +10 -0
  40. scrollback/web/static/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  41. scrollback/web/static/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  42. scrollback/web/static/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  43. scrollback/web/static/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  44. scrollback/web/static/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  45. scrollback/web/static/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
  46. scrollback/web/static/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  47. scrollback/web/static/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
  48. scrollback/web/static/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
  49. scrollback/web/static/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  50. scrollback/web/static/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
  51. scrollback/web/static/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  52. scrollback/web/static/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  53. scrollback/web/static/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  54. scrollback/web/static/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
  55. scrollback/web/static/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  56. scrollback/web/static/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  57. scrollback/web/static/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  58. scrollback/web/static/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  59. scrollback/web/static/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  60. scrollback/web/static/vendor/katex/katex.min.css +1 -0
  61. scrollback/web/static/vendor/katex/katex.min.js +1 -0
  62. scrollback/web/static/vendor/marked.min.js +6 -0
  63. scrollback/web/static/vendor/purify.min.js +3 -0
  64. scrollback/webopen.py +96 -0
  65. scrollback-0.1.0.dist-info/METADATA +391 -0
  66. scrollback-0.1.0.dist-info/RECORD +69 -0
  67. scrollback-0.1.0.dist-info/WHEEL +4 -0
  68. scrollback-0.1.0.dist-info/entry_points.txt +4 -0
  69. scrollback-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,391 @@
1
+ Metadata-Version: 2.4
2
+ Name: scrollback
3
+ Version: 0.1.0
4
+ Summary: Navigate, search, copy, and export your AI coding-agent sessions (opencode, Claude Code, ...) from one local, read-only tool.
5
+ Project-URL: Homepage, https://github.com/a-attia/scrollback
6
+ Project-URL: Repository, https://github.com/a-attia/scrollback
7
+ Project-URL: Issues, https://github.com/a-attia/scrollback/issues
8
+ Author: Ahmed Attia
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: ai-agent,claude-code,cli,local-first,opencode,session-history,transcript
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Environment :: Web Environment
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
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 :: Utilities
25
+ Requires-Python: >=3.10
26
+ Provides-Extra: all
27
+ Requires-Dist: fastapi>=0.110; extra == 'all'
28
+ Requires-Dist: jinja2>=3.1; extra == 'all'
29
+ Requires-Dist: pywebview>=5.0; extra == 'all'
30
+ Requires-Dist: rich>=13.0; extra == 'all'
31
+ Requires-Dist: uvicorn>=0.29; extra == 'all'
32
+ Provides-Extra: app
33
+ Requires-Dist: fastapi>=0.110; extra == 'app'
34
+ Requires-Dist: jinja2>=3.1; extra == 'app'
35
+ Requires-Dist: pywebview>=5.0; extra == 'app'
36
+ Requires-Dist: uvicorn>=0.29; extra == 'app'
37
+ Provides-Extra: dev
38
+ Requires-Dist: fastapi>=0.110; extra == 'dev'
39
+ Requires-Dist: httpx>=0.27; extra == 'dev'
40
+ Requires-Dist: pytest>=8.0; extra == 'dev'
41
+ Requires-Dist: rich>=13.0; extra == 'dev'
42
+ Requires-Dist: ruff>=0.4; extra == 'dev'
43
+ Requires-Dist: uvicorn>=0.29; extra == 'dev'
44
+ Provides-Extra: rich
45
+ Requires-Dist: rich>=13.0; extra == 'rich'
46
+ Provides-Extra: screenshots
47
+ Requires-Dist: fastapi>=0.110; extra == 'screenshots'
48
+ Requires-Dist: jinja2>=3.1; extra == 'screenshots'
49
+ Requires-Dist: playwright>=1.40; extra == 'screenshots'
50
+ Requires-Dist: pywebview>=5.0; extra == 'screenshots'
51
+ Requires-Dist: rich>=13.0; extra == 'screenshots'
52
+ Requires-Dist: uvicorn>=0.29; extra == 'screenshots'
53
+ Provides-Extra: web
54
+ Requires-Dist: fastapi>=0.110; extra == 'web'
55
+ Requires-Dist: jinja2>=3.1; extra == 'web'
56
+ Requires-Dist: pywebview>=5.0; extra == 'web'
57
+ Requires-Dist: uvicorn>=0.29; extra == 'web'
58
+ Description-Content-Type: text/markdown
59
+
60
+ # scrollback
61
+
62
+ [![CI](https://github.com/a-attia/scrollback/actions/workflows/ci.yml/badge.svg)](https://github.com/a-attia/scrollback/actions/workflows/ci.yml)
63
+
64
+ Browse, search, copy, and export your AI coding-agent sessions from one
65
+ local, read-only tool. scrollback reads the conversation history that
66
+ agents like **opencode** and **Claude Code** already keep on disk and gives
67
+ you a single, consistent view across them — from a scriptable command line
68
+ or a local web app.
69
+
70
+ Everything is local-first and strictly **read-only**: scrollback never
71
+ modifies, locks for writing, or uploads your data.
72
+
73
+ You can use it two ways. From the **command line**, list, search, and export
74
+ your sessions in a single scriptable tool:
75
+
76
+ ![scrollback listing recent sessions in the terminal.](assets/screenshots/cli.svg)
77
+
78
+ Or open the **local web app** to read a transcript in full — with rendered
79
+ Markdown, syntax-highlighted code, and typeset LaTeX math:
80
+
81
+ ![The scrollback web app showing a session list beside a transcript with
82
+ rendered Markdown, highlighted code, and typeset equations.](assets/screenshots/web.png)
83
+
84
+ Both views read the same on-disk session stores, so you can jump between
85
+ them freely. (The screenshots above use synthetic demo data.)
86
+
87
+ > **For AI agents:** read [`CONTRIBUTING.md`](CONTRIBUTING.md) for the
88
+ > project conventions. This README is for human readers.
89
+
90
+ ## Contents
91
+
92
+ - [Why scrollback](#why-scrollback)
93
+ - [Install](#install)
94
+ - [Quick start](#quick-start)
95
+ - [The command line](#the-command-line)
96
+ - [The web app](#the-web-app)
97
+ - [Running it as an app](#running-it-as-an-app)
98
+ - [Fast search (optional index)](#fast-search-optional-index)
99
+ - [Supported sources](#supported-sources)
100
+ - [Configuration](#configuration)
101
+ - [Safety](#safety)
102
+ - [Development](#development)
103
+ - [License](#license)
104
+
105
+ ## Why scrollback
106
+
107
+ AI coding agents persist rich session data locally, but each in its own
108
+ format and with no convenient way to browse that history or take it with
109
+ you. scrollback fills that gap with four things:
110
+
111
+ - **See** any past conversation as a readable transcript.
112
+ - **Search** across every session by keyword (title or full text).
113
+ - **Export** a session to Markdown, JSON, HTML, or plain text.
114
+ - **Copy** a message or a whole session straight to your clipboard.
115
+
116
+ Its niche among similar tools: pure Python, works equally from the
117
+ **CLI and a web UI**, reads **multiple agents** directly from their live
118
+ on-disk stores (no sync step, no plugins, no upload), and treats
119
+ **export and copy** as first-class.
120
+
121
+ ## Install
122
+
123
+ ```bash
124
+ pip install "scrollback[all]" # CLI + web app + native window + colour
125
+ ```
126
+
127
+ Requires Python 3.10+. The bare CLI has **no runtime dependencies**
128
+ (standard library only); optional features come from extras:
129
+
130
+ - `"scrollback[web]"` — the local web app (FastAPI, uvicorn) and the native
131
+ app window (pywebview).
132
+ - `"scrollback[rich]"` — coloured terminal output.
133
+ - `"scrollback[all]"` — everything a user might want at runtime (`web` + `rich`).
134
+
135
+ If you'd rather keep it isolated from your system Python (recommended, but
136
+ optional), [`pipx`](https://pipx.pypa.io) installs it in its own environment
137
+ and still puts the `scrollback` command on your PATH:
138
+
139
+ ```bash
140
+ pipx install "scrollback[all]"
141
+ ```
142
+
143
+ Either way, plain `pip` works the same; `pipx` is just a convenience.
144
+
145
+ From a local clone (for development), use an editable install with the dev
146
+ extra:
147
+
148
+ ```bash
149
+ pip install -e ".[web,dev]"
150
+ ```
151
+
152
+ ## Quick start
153
+
154
+ ```bash
155
+ scrollback doctor # what was detected on this machine?
156
+ scrollback list # recent sessions, newest first
157
+ scrollback show latest # print the most recent transcript
158
+ scrollback web # open the browser UI
159
+ ```
160
+
161
+ `scrollback doctor` is the best first command: it reports which agents
162
+ were found, how many sessions each has, and which optional features are
163
+ available.
164
+
165
+ ## The command line
166
+
167
+ The CLI is organised around a few verbs. Commands that operate on a single
168
+ session accept a **selector**: a full id, a unique prefix, a
169
+ source-qualified id (`opencode:ses_0eae9810`), or the keyword `latest`.
170
+
171
+ ### Listing and viewing
172
+
173
+ ```bash
174
+ scrollback list --source opencode -n 10 # one source, 10 rows
175
+ scrollback list --dir myproject # filter by directory substring
176
+ scrollback list -q "refactor" # filter by title substring
177
+ scrollback list --since 2026-06-01 --until 2026-06-30 # date range
178
+ scrollback list --usage # add cost + token (in/out) columns
179
+ scrollback list -n 20 --page 2 # pagination (page size = --limit)
180
+
181
+ scrollback show latest --reasoning # include the model's thinking
182
+ scrollback show <selector> --no-tools # hide tool calls and output
183
+ ```
184
+
185
+ By default, subagent sessions (for example opencode `@explore` subagents)
186
+ are **folded** under their parent; pass `--no-fold` to list them flat.
187
+ Output is coloured when the `rich` extra is installed and the output is a
188
+ terminal; piping, or `--plain`, falls back to plain text.
189
+
190
+ ### Searching
191
+
192
+ ```bash
193
+ scrollback search "merge conflict" # full-text across all sessions
194
+ scrollback search "ssh" --source opencode --json
195
+ ```
196
+
197
+ Search scans message text across sessions. On a large history you can make
198
+ it near-instant with an [optional index](#fast-search-optional-index).
199
+
200
+ ### Exporting and copying
201
+
202
+ ```bash
203
+ scrollback export latest -f markdown -o session.md
204
+ scrollback export <selector> -f html -o session.html
205
+ scrollback export <selector> -f html --math rendered -o session.html
206
+ scrollback export <selector> -f json # to stdout
207
+ scrollback copy latest -f markdown # render and copy to the clipboard
208
+ ```
209
+
210
+ The formats are `markdown` (`md`), `json`, `html`, and `text` (`txt`).
211
+ Markdown, HTML, and text honour `--reasoning` (include the model's
212
+ thinking) and `--no-tools` (omit tool calls and their output); JSON is a
213
+ faithful structured dump with bulky raw blobs stripped for readability.
214
+ Exported HTML and Markdown render the assistant's Markdown with syntax-
215
+ highlighted code, and the HTML is a self-contained file that prints well.
216
+
217
+ Mathematical notation in delimited LaTeX (`$...$`, `$$...$$`, `\(...\)`,
218
+ `\[...\]`) is preserved verbatim in every format, never mangled by the
219
+ Markdown pass. `--math` controls how the HTML export treats it: `raw`
220
+ (verbatim source, the default), `latex` (verbatim, marked never-to-typeset
221
+ — best for pasting into a paper), or `rendered` (typeset with KaTeX, which
222
+ is embedded into the file with its fonts so the equations render offline).
223
+ In the web app the same choice is a `math:` toggle in the transcript header.
224
+
225
+ ### Stats and resume
226
+
227
+ ```bash
228
+ scrollback stats # totals, by-source + top projects
229
+ scrollback resume latest # print the native resume command
230
+ scrollback resume <selector> --copy # ...and copy it to the clipboard
231
+ ```
232
+
233
+ `stats` aggregates session counts, message/token/cost totals, and your
234
+ busiest projects. `resume` prints the command to continue a session in its
235
+ own agent (for example `opencode --session <id>` or `claude --resume <id>`),
236
+ with a `cd` into the session's project directory.
237
+
238
+ ## The web app
239
+
240
+ `scrollback web` starts a local, read-only browser UI — FastAPI plus a
241
+ small vanilla-JavaScript frontend with no build step — bound to
242
+ `127.0.0.1`. Open it with `scrollback web` (a browser tab),
243
+ `scrollback web --window` (a standalone browser window), or
244
+ `scrollback web --app` (a native desktop window; see
245
+ [Running it as an app](#running-it-as-an-app)).
246
+
247
+ What it offers:
248
+
249
+ - A **session list** with source-filter chips, date filters, and a
250
+ **home** button to reset everything; it loads incrementally as you
251
+ scroll.
252
+ - An explicit **search scope** toggle — search session **titles**, message
253
+ **contents**, or both at once (combined results are grouped).
254
+ - **Subagents** collapsed under their parent, expandable on demand
255
+ (including Claude Code's nested sidechain transcripts).
256
+ - A **transcript reader** with a **collapsible** frozen header (auto-
257
+ collapses as you scroll; toggle with `h`) over a scrolling message body,
258
+ **Markdown rendering with syntax highlighting**, **LaTeX math** (source /
259
+ paste-ready / typeset), in-transcript find, show-reasoning / show-tools
260
+ toggles, and per-message and per-session copy.
261
+ - **Export** (Markdown / HTML / JSON), **print**, a **light/dark theme**,
262
+ and **keyboard navigation** (`/` search, `j`/`k` move, `Enter` open,
263
+ `f` find, `h` collapse header, `Esc` blur).
264
+
265
+ Large transcripts open instantly because the app loads a session's header
266
+ first and then pages messages in as you scroll, rather than transferring an
267
+ entire multi-megabyte transcript at once. Deep links work too: the open
268
+ session is reflected in the URL hash (`#opencode/<id>`), and `?q=<text>`
269
+ pre-fills a content search.
270
+
271
+ ## Running it as an app
272
+
273
+ You don't have to type a command every time. After `pip install ".[web]"`:
274
+
275
+ - **Short commands** are on your `PATH`: `scrollback-web` (a browser tab)
276
+ and `scrollback-app` (a native window).
277
+ - **A double-clickable launcher** is one command away:
278
+
279
+ ```bash
280
+ scrollback install-launcher # both: Desktop launcher + .app (macOS)
281
+ scrollback install-launcher --desktop # only the Desktop launcher
282
+ scrollback install-launcher --app-bundle # only the ~/Applications/.app (macOS)
283
+ ```
284
+
285
+ With no flags it installs everything for your OS; the two flags let you
286
+ pick just one. The Desktop launcher is `scrollback.command` on macOS,
287
+ `scrollback.bat` on Windows, and an application-menu entry plus
288
+ `scrollback.sh` on Linux. `--app-bundle` builds an
289
+ `~/Applications/scrollback.app` on macOS and falls back to the Desktop
290
+ launcher on other platforms (where there is no `.app`). Use `--dest <dir>`
291
+ to place artifacts elsewhere.
292
+
293
+ The launchers open a **native window** via pywebview when it is available:
294
+ no browser tab, no terminal, and **closing the window stops the server and
295
+ frees the port**. On a system where pywebview cannot run (for example a
296
+ headless Linux box without a GTK/Qt WebKit backend), scrollback falls back
297
+ to a standalone browser window that auto-stops the server shortly after the
298
+ window closes. All of this behaviour is decided in Python, so the launcher
299
+ scripts stay free of OS-specific assumptions and ship inside the package
300
+ for `pip install` users.
301
+
302
+ ## Fast search (optional index)
303
+
304
+ By default, search is a lexical scan over your live data: zero setup,
305
+ always correct, but its cost grows with the size of your history. For a
306
+ large corpus, build an optional full-text index:
307
+
308
+ ```bash
309
+ scrollback index # one-time build; re-run to update (incremental)
310
+ scrollback index --stats # show what's indexed
311
+ scrollback index --clear # delete the index
312
+ ```
313
+
314
+ The index is a separate SQLite FTS5 database at
315
+ `~/.cache/scrollback/index.db` (override with `SCROLLBACK_INDEX`). It is
316
+ derived and disposable: your source data is never modified, and deleting
317
+ the index simply reverts to the lexical scan. Re-running `index` only
318
+ re-processes new or changed sessions and prunes deleted ones; the web app
319
+ also refreshes it in the background on startup when it is stale.
320
+
321
+ Once built, both the CLI and the web app use it automatically, turning a
322
+ multi-second query into a few milliseconds. If your Python's SQLite was
323
+ built without FTS5, `index` says so and search keeps working without it.
324
+
325
+ ## Supported sources
326
+
327
+ | Source | Reads | Default location |
328
+ |:-------------|:-----------------------------------------------------------|:---------------------------------------|
329
+ | `opencode` | SQLite (`session` / `message` / `part`), read-only | `~/.local/share/opencode/opencode.db` |
330
+ | `claudecode` | per-project JSONL transcripts + nested subagent sidechains | `~/.claude/projects/` |
331
+ | `codex` | per-session `rollout-*.jsonl` rollouts | `~/.codex/sessions/` |
332
+ | `aider` | per-project `.aider.chat.history.md` Markdown logs | set `SCROLLBACK_AIDER_DIRS` to opt in |
333
+
334
+ More agents (Gemini CLI, Zed, VS Code Copilot Chat, GitHub Copilot CLI) are
335
+ researched and queued — see [`ROADMAP.md`](ROADMAP.md).
336
+
337
+ Adding another agent is a small, self-contained change: implement the
338
+ `Source` interface in `src/scrollback/sources/base.py` and register it in
339
+ `src/scrollback/sources/registry.py`. The CLI, search, export, web app,
340
+ and index all work against the common model automatically — see the
341
+ opencode (SQLite) and Claude Code (JSONL) adapters as references, and
342
+ [`CONTRIBUTING.md`](CONTRIBUTING.md) for the conventions.
343
+
344
+ ## Configuration
345
+
346
+ scrollback reads each agent's data from its default location, but you can
347
+ point it elsewhere, and you can control how the web server binds:
348
+
349
+ | Variable | Purpose |
350
+ |:--------------------------|:------------------------------------------------------------|
351
+ | `SCROLLBACK_OPENCODE_DB` | path to `opencode.db` |
352
+ | `SCROLLBACK_CLAUDE_DIR` | path to `~/.claude` or `~/.claude/projects` |
353
+ | `SCROLLBACK_CODEX_DIR` | path to `~/.codex` or `~/.codex/sessions` |
354
+ | `SCROLLBACK_AIDER_DIRS` | colon-separated dirs to scan for Aider history (opt-in) |
355
+ | `SCROLLBACK_PORT` | web server port (default `8765`; or use `--port`) |
356
+ | `SCROLLBACK_HOST` | web server bind host (default `127.0.0.1`; or use `--host`) |
357
+ | `SCROLLBACK_INDEX` | path to the search index database |
358
+
359
+ The web server defaults to `127.0.0.1`. If the chosen port is busy,
360
+ scrollback automatically picks the next free one (`--strict-port` fails
361
+ instead). Binding to a non-loopback host prints a warning, since the
362
+ read-only API is unauthenticated.
363
+
364
+ ## Safety
365
+
366
+ scrollback is read-only by design, and the design is enforced:
367
+
368
+ - The opencode SQLite database is opened with `mode=ro` — it is never
369
+ created or written, and reads are safe against a live write-ahead log.
370
+ - Claude Code JSONL files are read as read-only.
371
+ - A test asserts the opencode database's modification time is unchanged
372
+ across reads (`tests/test_sources_live.py`).
373
+ - The web app binds to localhost, rejects unexpected `Host` headers (a
374
+ DNS-rebinding guard), and sanitizes rendered transcript content.
375
+
376
+ ## Development
377
+
378
+ ```bash
379
+ pip install -e ".[web,dev]"
380
+ pytest -q # tests
381
+ ruff check src tests # lint
382
+ ```
383
+
384
+ See [`CONTRIBUTING.md`](CONTRIBUTING.md) for project conventions (the
385
+ read-only invariant, stdlib-first dependencies, platform-agnostic code,
386
+ and how to add a new agent source) and [`CHANGELOG.md`](CHANGELOG.md) for
387
+ what has landed so far.
388
+
389
+ ## License
390
+
391
+ MIT — see [`LICENSE`](LICENSE).
@@ -0,0 +1,69 @@
1
+ scrollback/__init__.py,sha256=Yohi9u5i1HXp4Jh8elf4T4B8xknbIvLZNg2ub4EsXTk,316
2
+ scrollback/cli.py,sha256=hWxTvwlcCqUnF1wIkJ9IIxYvZ5V4n2qFV33T9w9Tnvo,41748
3
+ scrollback/clipboard.py,sha256=FMpTsRsrGVbXBbdJRyo1cAethcB6ZRs4OAJCagkNvqE,1005
4
+ scrollback/export.py,sha256=MfXG2QDjNNTqzk9xz2Hvlm733oaS-6zsyTbLdZ4pPCw,11131
5
+ scrollback/fts.py,sha256=h9NsQpOqOIndyDsMHeBtx4aFNfbbqwRUVInxbIWgyfE,11442
6
+ scrollback/highlight.py,sha256=P3ocx_6Q_sBapWfq_3cjclq44hQK3RY8kfeJNrKHDxQ,4859
7
+ scrollback/katexbundle.py,sha256=2hAPxJ4SpJ9AxtREHzmqKCa4kSL_Kjrrp-7ciSnUnVM,2888
8
+ scrollback/launcher_install.py,sha256=iI2lACmCMhWLoiggXTV1qQBskjvyctEUC5HfOoxIZjA,8367
9
+ scrollback/mathspan.py,sha256=sMU8LAm513Rq2BlVD9Ax4ybjNMk_YIPGA2UauXKLVs8,6821
10
+ scrollback/minimd.py,sha256=YqzP7-ZCZP1YV7eYak6n6CoSF-I5f77WNjKe3xJAets,7600
11
+ scrollback/models.py,sha256=9H6YbHRN-27Fa_16eAqhYaSjN1hYAT81bv02rDOC1fY,4277
12
+ scrollback/serialize.py,sha256=apzTWeXqVNhgIYLYC_5UZQRoURZ0EnQe1E-D34B-BZQ,2271
13
+ scrollback/serverconfig.py,sha256=TAH9bscAI82ksCMOlVQDybxfg8OPEYGU4-GZqMGKftc,2011
14
+ scrollback/store.py,sha256=QZt7LCsAkA9MTHOEGhrD8FnMNATo1cw5cKFxQTfcTI8,14424
15
+ scrollback/termrender.py,sha256=WXw7DdG2fH3T3GVvnC5rCVCH0XU588hdMYmEh3DZapA,5869
16
+ scrollback/webopen.py,sha256=979_OUxxFIxhaSgytB0Xle6AawGdBEMwa2ckOQVahcA,3573
17
+ scrollback/assets/icon-256.png,sha256=WVskWeWUXhwbqiFIKm3MVGxTwP5RRae9hKKZCvWmyX0,6397
18
+ scrollback/assets/icon.icns,sha256=MDGD1hXJXeIPRuH5HOmeVe91lsuiqe73o2rPvTWJmJk,114460
19
+ scrollback/launchers/scrollback.bat,sha256=It_rJ0e8kobuHz25mjKyOh274DGwIgjiT1hDSkaoBzU,420
20
+ scrollback/launchers/scrollback.command,sha256=SoP_XqFggHZ0sts-JuYZuaARxRJ4eben8-k4-PRGm4s,693
21
+ scrollback/launchers/scrollback.desktop,sha256=bfiUx2FgX4K48yT5DxgKHVCkfGZ0bg-51kNQihD3PIA,363
22
+ scrollback/launchers/scrollback.sh,sha256=LqBTKXgTbpfKuEdPrCxu7hqtdIqw-PaD3tpmT-Nmq3o,435
23
+ scrollback/sources/__init__.py,sha256=pyiM6nABWX56t8dxM0tA53q4_dqjSWySkbHMfEovECQ,263
24
+ scrollback/sources/aider.py,sha256=Xzd0cg-IxqBrpNktvCG-89Aze8btGxHYcK6fiQQS5zo,8712
25
+ scrollback/sources/base.py,sha256=pb2n4pIr-tzzERDiLopUFNoAw5mHNgbq2gmJbRpOafE,4064
26
+ scrollback/sources/claudecode.py,sha256=gxe3PQaakbsxXZVeaqQEcSydEffUx11I-k0VEwjAN1E,23050
27
+ scrollback/sources/codex.py,sha256=CTMOGX3b1W30wTniPNz4wielyqPEYTGrX9CBubRoz-M,9647
28
+ scrollback/sources/opencode.py,sha256=T5CDQgcWVo1mfS45JzMy0RJifezV5sYqa8GxlSqHMh4,12143
29
+ scrollback/sources/registry.py,sha256=qT7dVs057mZ1uc19MfE-pLCRvS2lKObo3FIHA-F6LHU,1033
30
+ scrollback/web/__init__.py,sha256=Fc0H7B-igSBI1bpUe9N12VRVJegzqWTtyjT2kpFvcg8,65
31
+ scrollback/web/app.py,sha256=NAZY_VwZrHmeVCYrFGYZiB_jMkusrx-3o2B2Q_osvpw,14062
32
+ scrollback/web/static/app.js,sha256=jBRye8hgeboOjqIKenCISNquQZtc-5DtosYkbFPKZMY,46470
33
+ scrollback/web/static/apple-touch-icon.png,sha256=Ca1lF0cMSjJfp7WI207Cvso8HNmue1X-CTNx4KSM8GQ,4748
34
+ scrollback/web/static/favicon.png,sha256=ELp1K-ZQazVPE4bEHOj15FFekKWPtxsn9Sq_yE_APOg,879
35
+ scrollback/web/static/favicon.svg,sha256=ztGZv1Umu7C4Fo3aGqIjrfgKAXu7xN8SOk-1g5v5OgA,1782
36
+ scrollback/web/static/index.html,sha256=zfNoE9dc-dpqfdjt_VGyMY31jttghkY3I2VOKzi4DJw,3080
37
+ scrollback/web/static/style.css,sha256=GT_M7MRsRYhY9ukQr15I1Q-W38jgGoCAE-Tlaf4wl6c,21509
38
+ scrollback/web/static/vendor/highlight.min.js,sha256=g3pvpbDHNrUrveKythkPMF2j_J7UFoHbUyFQcFe1yEY,121727
39
+ scrollback/web/static/vendor/hljs-dark.min.css,sha256=nyCNAiECsdDHrr_s2OQsp5l9XeY2ZJ0rMepjCT2AkBk,1315
40
+ scrollback/web/static/vendor/hljs-light.min.css,sha256=Oppd74ucMR5a5Dq96FxjEzGF7tTw2fZ_6ksAqDCM8GY,1309
41
+ scrollback/web/static/vendor/marked.min.js,sha256=Ffq85bZYmLMrA_XtJen4kacprUwNbYdxEKd0SqhHqJQ,35479
42
+ scrollback/web/static/vendor/purify.min.js,sha256=ZAdXaZOlqhMD6vn--5Xlz8HAyAZFvTcX22cXJ-a1W5E,21531
43
+ scrollback/web/static/vendor/katex/katex.min.css,sha256=cXvJrnhTth8PdkVd3fDs1PUnp4P0LeKsJGhImcHEYlg,23335
44
+ scrollback/web/static/vendor/katex/katex.min.js,sha256=5r_l3uvUx8zScgVbq2O9OrLHO5B7bmoi01J0CoE4H9Q,275414
45
+ scrollback/web/static/vendor/katex/fonts/KaTeX_AMS-Regular.woff2,sha256=DN04fJWQoan5eUVgAi27WWVKfYbxh6oMgUla1C06cwg,28076
46
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2,sha256=3ncB5Czx9M8LdmwD-yeXcgfu4vT9XXb6ghiEBtpD6kw,6912
47
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2,sha256=XVPnCtYHwjUhYt7J4JI_tU7Nr6zL9gTNjc99APrLmJs,6908
48
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2,sha256=dERO_Vk8AF4_RXO0RSRwTArwqTf-kRzKnpQGjQ0UDT8,11348
49
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2,sha256=UYFNJw0G_wJV26B5mZT6TYyE0R8JlR1HWV9Kux82Atw,11316
50
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Main-Bold.woff2,sha256=D2DRuJeTjskYyM4HMJJBG6-UOPZzlGVpP_GLD50gsCE,25324
51
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2,sha256=mc1Co8By2Rjy9EmEqAfPeqFuE1Rf0IdfwHxsZfmecVs,16780
52
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Main-Italic.woff2,sha256=l0ecpszpBqvJYeyslvql-couYbjnZw1HWCa83umnwmc,16988
53
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Main-Regular.woff2,sha256=wjQs2Lhp4BdSqTIdwXIT_EDU0Ex5aIwdQ_LPMWq9eGY,26272
54
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2,sha256=3Ec0TbtstbZVyEYNVh9N9fUBuQyAStPGzsZf4yI1GrE,16400
55
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Math-Italic.woff2,sha256=evWMXsjxMqLd3pAnxteBTezOTTuCKhEZKkKiDi6XMmQ,16440
56
+ scrollback/web/static/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2,sha256=6ZrlEUS_EjLvzBv-Wt02JixoZrD6qyT6dXQOG5hXemI,12216
57
+ scrollback/web/static/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2,sha256=ALJqyCXiCVBWOW4FU7isJtP4rRWMOCbii0xFs4XEcUo,12028
58
+ scrollback/web/static/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2,sha256=aOjHPvQq_TzOxYvw-6MCzORIk45_wCCl4x-KlS7uE0I,10344
59
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Script-Regular.woff2,sha256=A21OlRSbaf-bzAzVV3Hv6yX_o5Ryk-aazXjVrDKMaEs,9644
60
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Size1-Regular.woff2,sha256=a0fEAWa22-IaXfyncYQT8hR_0jmb4bpgXYrTnO3yXf4,5468
61
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Size2-Regular.woff2,sha256=0ExUIZ-ersbU1P1C37KHhZdaR5TWsvxx5Wa5zW24Qt0,5208
62
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Size3-Regular.woff2,sha256=c9WRJxsWBJYMsQu5D-4CFnCvcpcBfg6YSAszLRH1GZU,3624
63
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Size4-Regular.woff2,sha256=pK99QURAocF5CCXPtwDPnPQ7DyxLBPDrxSMBGtmFPsA,4928
64
+ scrollback/web/static/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2,sha256=cdUX1ngneHz6vfGGkUzDNY7aU543kxlB8rL9SiH2jAs,13568
65
+ scrollback-0.1.0.dist-info/METADATA,sha256=OsVo669oyfwE4eZa8x-bWoB0DH9n07LGwVqgfb86MdQ,17276
66
+ scrollback-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
67
+ scrollback-0.1.0.dist-info/entry_points.txt,sha256=8dKwY4-SwjADuMfKRzwPNHrOsw0GnARmMgu_6Fdw7po,133
68
+ scrollback-0.1.0.dist-info/licenses/LICENSE,sha256=SNaLOpUWPjwl91fMGbI5KhB0aJo-hYkzZjyuFaqKlUI,1068
69
+ scrollback-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+ scrollback = scrollback.cli:main
3
+ scrollback-app = scrollback.cli:main_app
4
+ scrollback-web = scrollback.cli:main_web
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ahmed Attia
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.