Save logs of claude code, and convert them into HTML
Project description
Claude Logging
Automatically keep logs of "claude code" sessions, and convert them to HTML.
Features
- Automatically log
claudesessions in~/.claude/logs - Convert logged session into HTML files
- Strips control characters and preserves text formatting
- Converts terminal output to styled HTML
- Supports syntax highlighting, bold text, and colors
- Includes line numbering and theme toggling in the HTML output
NOTE: this tool has largely been written by claude itself. The quality of the code is a direct consequence of it.
Installation
The easiest way is to run it without need of installation through uxv:
uvx claude-logging
This will start a normal claude session, but will record the log in ~/.claude/logs.
For automatic logging of every invocation of claude, you can put an alias
in your ~/.bashrc or equivalent:
alias claude="uxv claude-logging"
If you prefer a more classical installation method, you can use pip:
pip install claude-logging
Usage
Default Mode: Record Claude Sessions
When you run the command claude-logging, it will:
- Create a log directory at
~/.claude/logs/if it doesn't exist - Generate a unique log filename based on your current directory and timestamp
- Run the
claudecommand with all provided arguments - Record the entire session to the log file
All the arguments are directly passed to the underyling claude program.
HTML Conversion Mode
Convert existing log files to HTML:
# Convert a log file to HTML
claude-logging dump ~/.claude/logs/my.log
# Bulk convert multiple files
claude-logging dump ~/.claude/logs/my*.log
# Output to a specific file
claude-logging dump ~/.claude/logs/my.log -o my.html
# Use stdin/stdout
cat logfile.log | claude-logging dump - > output.html
Example logs
These are some of the sessions in which I used claude to write claude-logging:
-
create ansi2html.py, which converts a terminal dump into a HTML page with proper colors and permalinks
-
write the pytermdump C extension and setup CI to build/publish wheels
You can click on a line or shift-click on a range of lines to generate a permalink to a specific part of the log. For example, this is when I asked claude not to build windows wheels.
How it works
Unfortunately claude doesn't seem to offer a way to get a structured log of
the conversation, so the only possible way is to get a dump of the terminal.
This is doable using the script program in linux, which records all
characters sent to a TTY:
script --flush --quiet --return --command "claude $*" "$LOG_FILE"
However, the resulting file is not directly usable, because claude is a rich
terminal application and it constantly redraws parts of the screen. The raw
log includes all characters ever sent to the TTY, including the ones which
are responsible to erase one or more lines, and the ones which are responsible
to redraw.
For example, for each key pressed by the user, claude erases and redraws the
whole input box. If you inspect a raw log files using less -R you can see it
clearly. This is part of the log generated by typing hello in the input box:
╭──────────────────────────────────────────────────────────────────────────────╮
│ > │
╰──────────────────────────────────────────────────────────────────────────────╯
! for bash mode · / for commands \⏎ for newline
╭──────────────────────────────────────────────────────────────────────────────╮
│ > Try "how do I log an error?" │
╰──────────────────────────────────────────────────────────────────────────────╯
! for bash mode · / for commands \⏎ for newline
╭──────────────────────────────────────────────────────────────────────────────╮
│ > h │
╰──────────────────────────────────────────────────────────────────────────────╯
! for bash mode · / for commands \⏎ for newline
╭──────────────────────────────────────────────────────────────────────────────╮
│ > he │
╰──────────────────────────────────────────────────────────────────────────────╯
! for bash mode · / for commands \⏎ for newline
╭──────────────────────────────────────────────────────────────────────────────╮
│ > hel │
╰──────────────────────────────────────────────────────────────────────────────╯
! for bash mode · / for commands \⏎ for newline
╭──────────────────────────────────────────────────────────────────────────────╮
│ > hell │
╰──────────────────────────────────────────────────────────────────────────────╯
! for bash mode · / for commands \⏎ for newline
╭──────────────────────────────────────────────────────────────────────────────╮
│ > hello │
╰──────────────────────────────────────────────────────────────────────────────╯
! for bash mode · / for commands \⏎ for newline
The solution is to "replay" all the commands sent to the terminal, in order to get the final state of the screen. For doing that we need to write a basic version of a terminal emulator: fortunately, we just need to support a handful number of ANSI escape sequences. This is the job of termdump.c and pytermdump.c
The core logic is in termdump.c, which takes a raw log file and produces the
"final state" of the terminal. Ironically, claude itself was not able to
produce a working version of termdump.c,
which was written by chatgpt.
Once we have the "dumped" version of the screen, we can convert it into HTML using ansi2html.py.
License
MIT License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file claude_logging-0.4.0.tar.gz.
File metadata
- Download URL: claude_logging-0.4.0.tar.gz
- Upload date:
- Size: 16.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d0b7f488fb8d6187218178db5d52e9120f8947d7f4dbfd2733424b7287dc6cf8
|
|
| MD5 |
5d032f74a79d592500cc8f85de79d5f2
|
|
| BLAKE2b-256 |
1b89bedb9562c465330b244adcf5809121822b97681569ccd55ed90a68d945ec
|
Provenance
The following attestation bundles were made for claude_logging-0.4.0.tar.gz:
Publisher:
build-and-publish.yml on antocuni/claude-logging
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
claude_logging-0.4.0.tar.gz -
Subject digest:
d0b7f488fb8d6187218178db5d52e9120f8947d7f4dbfd2733424b7287dc6cf8 - Sigstore transparency entry: 181062272
- Sigstore integration time:
-
Permalink:
antocuni/claude-logging@d5a490f312abbb0ea25c321254ae679b81aaba37 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/antocuni
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-and-publish.yml@d5a490f312abbb0ea25c321254ae679b81aaba37 -
Trigger Event:
release
-
Statement type:
File details
Details for the file claude_logging-0.4.0-cp38-abi3-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: claude_logging-0.4.0-cp38-abi3-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 28.3 kB
- Tags: CPython 3.8+, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f85ec0d690b6b3aafb16d6eb88e0f6f3b91212e62a69fa963be04c028ab5ac71
|
|
| MD5 |
6fcff1ea0c26daa0f26e581675c1b003
|
|
| BLAKE2b-256 |
259aa0f3107a013c895d6410f35766d1abbba5873828efdb254d20aef7ef2702
|
Provenance
The following attestation bundles were made for claude_logging-0.4.0-cp38-abi3-musllinux_1_2_x86_64.whl:
Publisher:
build-and-publish.yml on antocuni/claude-logging
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
claude_logging-0.4.0-cp38-abi3-musllinux_1_2_x86_64.whl -
Subject digest:
f85ec0d690b6b3aafb16d6eb88e0f6f3b91212e62a69fa963be04c028ab5ac71 - Sigstore transparency entry: 181062284
- Sigstore integration time:
-
Permalink:
antocuni/claude-logging@d5a490f312abbb0ea25c321254ae679b81aaba37 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/antocuni
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-and-publish.yml@d5a490f312abbb0ea25c321254ae679b81aaba37 -
Trigger Event:
release
-
Statement type:
File details
Details for the file claude_logging-0.4.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: claude_logging-0.4.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 30.2 kB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4dae2e4a56439d6bf88938af4f791ffb693d90e52cf645f70300c881970c2241
|
|
| MD5 |
e4583419b05483a876c0a32e362f31b0
|
|
| BLAKE2b-256 |
e3c0a8d5c6da8e0564a88e531610780870921f4a0ae70328ce54db57fa621511
|
Provenance
The following attestation bundles were made for claude_logging-0.4.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
build-and-publish.yml on antocuni/claude-logging
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
claude_logging-0.4.0-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl -
Subject digest:
4dae2e4a56439d6bf88938af4f791ffb693d90e52cf645f70300c881970c2241 - Sigstore transparency entry: 181062279
- Sigstore integration time:
-
Permalink:
antocuni/claude-logging@d5a490f312abbb0ea25c321254ae679b81aaba37 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/antocuni
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-and-publish.yml@d5a490f312abbb0ea25c321254ae679b81aaba37 -
Trigger Event:
release
-
Statement type: