Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
bef9bfd
Apache 2
simonw Dec 24, 2025
cd8fd37
Update pyproject with license
simonw Dec 24, 2025
a0b8f81
Release 0.1
simonw Dec 24, 2025
72dd821
description and project.urls
simonw Dec 24, 2025
651a77a
Move to click and click-default-group for argument parsing
simonw Dec 25, 2025
e1fd054
list-web and import commands using unofficial Claude API
simonw Dec 25, 2025
62fe91f
New option --gist to publish straight to a Gist via gh CLI
simonw Dec 25, 2025
9fe9efe
Drop threshold for index inclusion from 1000 to 300 chars
simonw Dec 25, 2025
e64da83
Show claude-code-publish import --gist in README
simonw Dec 25, 2025
1001086
--json option for saving session JSON
simonw Dec 25, 2025
201c29f
Fixed bug where index.html did not always show long summaries
simonw Dec 25, 2025
3ec9ca6
Ran black
simonw Dec 25, 2025
944741d
--open option to open directly in browser
simonw Dec 25, 2025
1ceafed
Release 0.2
simonw Dec 25, 2025
fc26566
AGENTS.md and CLAUDE.md
simonw Dec 25, 2025
2b38831
Add version flag to CLI (#1)
simonw Dec 25, 2025
441d339
Add support for local JSONL session format
claude Dec 25, 2025
0385cd0
Restructure CLI commands per feedback
claude Dec 25, 2025
d08c12e
Add -a/--output-auto flag to all commands
claude Dec 25, 2025
1ae3016
Add Jinja2 templates for HTML generation (#2)
simonw Dec 25, 2025
c2624ff
Add autouse fixture to mock webbrowser.open in tests
simonw Dec 25, 2025
f59e0c8
Update README for latest changes
simonw Dec 25, 2025
4f6a8ee
Rename tool from claude-code-publish to claude-code-transcripts
simonw Dec 25, 2025
3491670
Release 0.3
simonw Dec 25, 2025
e6fe3e2
Link to blog post
simonw Dec 25, 2025
c420f74
Test on windows and Linux and Mac
simonw Dec 26, 2025
2a901e3
Fix Windows Unicode encoding errors when writing HTML files (#7)
simonw Dec 26, 2025
872aba9
Fix fragment navigation for gistpreview.github.io URLs (#13)
simonw Dec 27, 2025
2fbd60c
Add batch command for converting all sessions to HTML archive (#11)
brendanbecker Dec 27, 2025
db23ce4
Re-arranged sections in README
simonw Dec 27, 2025
48de810
Add support for rendering images with base64 data URLs
simonw Dec 27, 2025
607454b
Fix handling of array content format in user messages
simonw Dec 27, 2025
f257360
Add search feature to index.html pages
simonw Dec 27, 2025
7e72788
Fix internal links in search results to include page file
simonw Dec 27, 2025
9279a2e
Extend header underline to include search box
simonw Dec 27, 2025
abdcec2
Add gistpreview.github.io support to search feature
simonw Dec 27, 2025
e580646
Fix gistpreview URL handling in search feature
simonw Dec 27, 2025
2fd459e
Fix search result links for gistpreview URL format
simonw Dec 27, 2025
f30bd91
Set search input font-size to 16px to avoid mobile zoom
simonw Dec 27, 2025
b8c1513
Hide search feature when page is opened from file:// protocol
simonw Dec 27, 2025
8816ce3
Fix search dialog visible before first use
simonw Dec 27, 2025
16cd674
Release 0.4
simonw Dec 27, 2025
8351f24
Add URL support to json command
claude Dec 29, 2025
1c457cc
Add ANSI escape code sanitization and content-block array rendering
ShlomoStept Dec 31, 2025
7242cd2
Add copy buttons to code blocks and tool results
ShlomoStept Dec 31, 2025
ee13ef8
Add syntax highlighting with Pygments for code blocks
ShlomoStept Dec 31, 2025
6ffbff3
Update TASKS.md and AGENTS.md with comprehensive documentation
ShlomoStept Dec 31, 2025
5169d88
Render content-block arrays fully
ShlomoStept Dec 31, 2025
8981b63
Pair tool_use with tool_result
ShlomoStept Dec 31, 2025
03c495a
Harden ANSI escape sanitization
ShlomoStept Dec 31, 2025
82a533f
Merge feature/ansi-sanitization: hardened ANSI regex with OSC/CSI/C1 …
ShlomoStept Dec 31, 2025
ef4b819
Merge feature/tool-use-result-pairing: pair tool_use with tool_result…
ShlomoStept Dec 31, 2025
5490fd4
Format code and update snapshots after merge
ShlomoStept Dec 31, 2025
70d36c9
Start Phase 2: collapsible cells and tool markdown
ShlomoStept Jan 1, 2026
008f43f
Add Markdown rendering for tool descriptions and JSON string values
ShlomoStept Jan 1, 2026
fe23fc5
Add collapsible cell structure for assistant messages
ShlomoStept Jan 1, 2026
fab6fa4
Add per-cell copy buttons for collapsible sections
ShlomoStept Jan 1, 2026
0f9c587
Add UI improvements for collapsible cells and tool rendering
ShlomoStept Jan 1, 2026
d662941
Implement comprehensive UI improvements for Phase 2
ShlomoStept Jan 1, 2026
379ef41
Fix JSON display mode and tabs alignment regressions
ShlomoStept Jan 1, 2026
62ff001
Implement Phase 2 remaining items: metadata subsection and tool icons
ShlomoStept Jan 1, 2026
9a877f2
Fix duplicate test method by renaming to unique name
ShlomoStept Jan 6, 2026
26acdcd
Refactor _github_repo to thread-safe contextvars
ShlomoStept Jan 6, 2026
ab65c8d
Add Clipboard API fallback for older browsers
ShlomoStept Jan 6, 2026
f167416
Merge pull request #6 from ShlomoStept/fix/phase2-ui-regressions
ShlomoStept Jan 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ permissions:

jobs:
test:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v6
Expand All @@ -23,5 +24,7 @@ jobs:
run: |
pip install -e . --group dev
- name: Run tests
env:
PYTHONUTF8: "1"
run: |
python -m pytest
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.DS_Store
__pycache__
uv.lock
.playwright-mcp/
161 changes: 161 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# Development Guide

This guide covers everything needed to contribute to claude-code-transcripts.

## Quick Start

```bash
# Clone and setup
git clone https://github.com/simonw/claude-code-transcripts.git
cd claude-code-transcripts

# Install uv if not already installed
# See: https://docs.astral.sh/uv/

# Install dependencies
uv sync --group dev

# Run tests
uv run pytest

# Run the development version
uv run claude-code-transcripts --help
```

## Project Structure

```
claude-code-transcripts/
├── src/claude_code_transcripts/
│ ├── __init__.py # Main implementation
│ └── templates/ # Jinja2 templates
│ ├── macros.html # Reusable macros
│ ├── page.html # Page template
│ ├── index.html # Index template
│ ├── base.html # Base template
│ └── search.js # Client-side search
├── tests/
│ ├── test_generate_html.py # Main test suite
│ ├── test_all.py # Batch command tests
│ ├── sample_session.json # Test fixture (JSON)
│ ├── sample_session.jsonl # Test fixture (JSONL)
│ └── __snapshots__/ # Snapshot test outputs
├── TASKS.md # Implementation roadmap
├── AGENTS.md # This file
└── pyproject.toml # Package configuration
```

## Running Tests

```bash
# Run all tests
uv run pytest

# Run specific test file
uv run pytest tests/test_generate_html.py

# Run specific test class
uv run pytest tests/test_generate_html.py::TestRenderContentBlock

# Run specific test
uv run pytest tests/test_generate_html.py::TestRenderContentBlock::test_text_block -v

# Run with verbose output
uv run pytest -v

# Run with stdout capture disabled (for debugging)
uv run pytest -s
```

## Code Formatting

Format code with Black before committing:

```bash
uv run black .
```

Check formatting without making changes:

```bash
uv run black . --check
```

## Test-Driven Development (TDD)

Always practice TDD: write a failing test, watch it fail, then make it pass.

1. Write a failing test for your change
2. Run tests to confirm it fails: `uv run pytest`
3. Implement the feature to make the test pass
4. Format your code: `uv run black .`
5. Run all tests to ensure nothing broke
6. Commit with a descriptive message

## Snapshot Testing

This project uses `syrupy` for snapshot testing. Snapshots are stored in `tests/__snapshots__/`.

Update snapshots when intentionally changing output:

```bash
uv run pytest --snapshot-update
```

## Making Changes

### Commit Guidelines

Commit early and often. Each commit should bundle:
- The test
- The implementation
- Documentation changes (if applicable)

Example commit message:
```
Add support for filtering sessions by date

- Add --since and --until flags to local command
- Filter sessions by modification time
- Add tests for date filtering
```

### Before Submitting a PR

1. All tests pass: `uv run pytest`
2. Code is formatted: `uv run black .`
3. Documentation updated if adding user-facing features
4. TASKS.md updated if completing a tracked task

## Key Files Reference

| File | Purpose |
|------|---------|
| `src/claude_code_transcripts/__init__.py` | Main implementation (~1300 lines) |
| `src/claude_code_transcripts/templates/macros.html` | Jinja2 macros for rendering |
| `tests/test_generate_html.py` | Main test suite |
| `tests/sample_session.json` | Test fixture data |
| `TASKS.md` | Implementation roadmap and status |

## Debugging Tips

```bash
# See full assertion output
uv run pytest -vv

# Stop on first failure
uv run pytest -x

# Run only failed tests from last run
uv run pytest --lf

# Run tests matching a pattern
uv run pytest -k "test_ansi"
```

## Architecture Notes

- CSS and JavaScript are embedded as string constants in `__init__.py`
- Templates use Jinja2 with autoescape enabled
- The `_macros` module exposes macros from `macros.html`
- Tool rendering follows the pattern: Python function → Jinja2 macro → HTML
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
201 changes: 201 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.

"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:

(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and

(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and

(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and

(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.

You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright [yyyy] [name of copyright owner]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Loading
Loading