feat: add --session-id flag for exporting a single #103
feat: add --session-id flag for exporting a single #103chloelee767 wants to merge 7 commits intodaaain:mainfrom
Conversation
Adds a new `--session-id` option to the CLI that exports a single conversation to HTML or Markdown without launching the TUI. Supports full session IDs and 8-char short prefixes, including archived sessions. https://claude.ai/code/session_01S99zF7j4LnfKCqbvyCXJV5
Tests cover input validation, session ID resolution (exact/prefix/ambiguous), output path logic, no-cache mode, and session title generation from cache metadata. https://claude.ai/code/session_01Gbx7zBdyjKkQq8frBfcP5M
📝 WalkthroughWalkthroughAdds a session-based export flow: a new Changes
Sequence Diagram(s)sequenceDiagram
participant User as User/CLI
participant CLI as claude_code_log/cli.py
participant Converter as claude_code_log/converter.py
participant Cache as Cache System
participant FS as File System
participant Renderer as Renderer
User->>CLI: Invoke CLI with --session-id
CLI->>CLI: Validate/normalize input_path
CLI->>Converter: generate_single_session_file(format, input_path, session_id, output, use_cache, image_mode)
Converter->>FS: Load project transcripts (JSONL)
Converter->>Converter: Resolve session_id (exact or prefix)
alt use_cache
Converter->>Cache: Load archived session metadata
Cache-->>Converter: Session cache/meta
end
Converter->>Converter: build_session_title(project_title, session_id, session_cache)
Converter->>Renderer: Render session content to format
Renderer-->>Converter: Rendered bytes/text
Converter->>FS: Write output file
FS-->>Converter: Output path
Converter-->>CLI: Return output path
CLI->>User: Print success message (and optionally open browser)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
claude_code_log/cli.py (1)
548-690:⚠️ Potential issue | 🟡 MinorAdd explicit conflict checks for
--session-idcombinations.
--session-idcan be silently ignored when combined with--tui(and is ambiguous with--all-projects). Fail fast with a clear CLI error.Suggested fix
try: + if session_id is not None and tui: + click.echo("Error: --session-id cannot be used with --tui", err=True) + sys.exit(1) + if session_id is not None and all_projects: + click.echo("Error: --session-id cannot be used with --all-projects", err=True) + sys.exit(1) + # Handle TUI mode if tui:🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@claude_code_log/cli.py` around lines 548 - 690, The CLI currently allows --session-id to be combined with conflicting flags (tui, all_projects) and may silently ignore session_id; add an explicit conflict check early in the command handler: if session_id is not None and tui is True or session_id is not None and all_projects is True, raise a clear click.UsageError or echo an error and sys.exit(1) so the command fails fast; update the top of the TUI/argument handling (near variables session_id, tui, all_projects) to validate these combinations before any project discovery/convert_project_path_to_claude_dir or generate_single_session_file calls, listing the conflicting flags in the message.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@claude_code_log/converter.py`:
- Around line 1680-1733: Single-session export currently passes raw
session_messages to renderer.generate_session and skips the deduplication step
used by the main export flow; locate the deduplication helper used elsewhere in
the codebase (e.g., dedupe_session_entries / deduplicate_messages / similar) and
apply it to session_messages (or via cache_manager if that provides dedupe)
before calling renderer.generate_session so duplicates/stutter are removed while
preserving existing use of session_messages, matched_id, session_title and
cache_manager.
- Around line 1640-1643: The code currently constructs cache_manager =
CacheManager(input_path, get_library_version()) when use_cache is true, but that
will raise and abort the export if CacheManager initialization fails (DB
lock/corruption/permission); wrap the CacheManager(...) call in a try/except
that catches Exception, logs the error (include exception details) and falls
back to disabling cache by setting cache_manager = None (and optionally set
use_cache = False) so the export proceeds without cache; reference the
CacheManager constructor call and the cache_manager variable when making this
change.
---
Outside diff comments:
In `@claude_code_log/cli.py`:
- Around line 548-690: The CLI currently allows --session-id to be combined with
conflicting flags (tui, all_projects) and may silently ignore session_id; add an
explicit conflict check early in the command handler: if session_id is not None
and tui is True or session_id is not None and all_projects is True, raise a
clear click.UsageError or echo an error and sys.exit(1) so the command fails
fast; update the top of the TUI/argument handling (near variables session_id,
tui, all_projects) to validate these combinations before any project
discovery/convert_project_path_to_claude_dir or generate_single_session_file
calls, listing the conflicting flags in the message.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1fba01b5-3cbf-465f-8e15-9df030ddff46
📒 Files selected for processing (4)
claude_code_log/cli.pyclaude_code_log/converter.pytest/test_cli.pytest/test_session_export.py
There was a problem hiding this comment.
🧹 Nitpick comments (1)
claude_code_log/converter.py (1)
1472-1486: Consider adding a docstring and tightening the type hint.This is a public helper now imported by
tui.py. A brief docstring would clarify its purpose. Additionally,Optional[Any]could beOptional[SessionCacheData]for better type safety.📝 Suggested improvement
def build_session_title( project_title: str, session_id: str, - session_cache: Optional[Any], + session_cache: Optional[SessionCacheData], ) -> str: + """Build a display title for a session. + + Uses the session summary if available, otherwise the first user message + preview (truncated to 50 chars), falling back to "Session {id[:8]}". + """ if session_cache:🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@claude_code_log/converter.py` around lines 1472 - 1486, Add a short docstring to build_session_title describing its purpose, parameters (project_title, session_id, session_cache) and return value; tighten the type hint of session_cache from Optional[Any] to Optional[SessionCacheData] (import or forward-declare SessionCacheData if needed) and ensure any attribute access (summary, first_user_message) aligns with that type. Keep the existing logic intact and update the function signature and docstring accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@claude_code_log/converter.py`:
- Around line 1472-1486: Add a short docstring to build_session_title describing
its purpose, parameters (project_title, session_id, session_cache) and return
value; tighten the type hint of session_cache from Optional[Any] to
Optional[SessionCacheData] (import or forward-declare SessionCacheData if
needed) and ensure any attribute access (summary, first_user_message) aligns
with that type. Keep the existing logic intact and update the function signature
and docstring accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: cff9a1a6-f1d3-44b6-b144-92588f7d143f
📒 Files selected for processing (2)
claude_code_log/converter.pyclaude_code_log/tui.py
There was a problem hiding this comment.
🧹 Nitpick comments (1)
claude_code_log/converter.py (1)
1661-1696: Consider lazy loading for single-session export performance.The function loads all messages from the directory (line 1661) before filtering to the target session (lines 1692-1696). For large projects, this is inefficient when exporting a single session.
This is acceptable for the current CLI use case, but if this becomes a hot path, consider:
- Using cache metadata to resolve session IDs without loading all messages
- Loading only the specific session's JSONL file when the full session ID is provided
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@claude_code_log/converter.py` around lines 1661 - 1696, The code currently calls load_directory_transcripts(input_path, cache_manager) and loads all messages into messages before resolving session_id; change this to resolve matched_id using cache metadata first (use cache_manager.get_cached_project_data() and project_cache.sessions) and only call load_directory_transcripts when necessary (e.g., if session_id is ambiguous or not found in cache), and if the provided session_id is a full ID, load just that session's JSONL file instead of the whole directory; update the logic around matched_id, messages, and session_messages (referencing load_directory_transcripts, cache_manager, project_cache, session_id, matched_id, messages, session_messages) so we lazily load transcripts for a single-session export.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@claude_code_log/converter.py`:
- Around line 1661-1696: The code currently calls
load_directory_transcripts(input_path, cache_manager) and loads all messages
into messages before resolving session_id; change this to resolve matched_id
using cache metadata first (use cache_manager.get_cached_project_data() and
project_cache.sessions) and only call load_directory_transcripts when necessary
(e.g., if session_id is ambiguous or not found in cache), and if the provided
session_id is a full ID, load just that session's JSONL file instead of the
whole directory; update the logic around matched_id, messages, and
session_messages (referencing load_directory_transcripts, cache_manager,
project_cache, session_id, matched_id, messages, session_messages) so we lazily
load transcripts for a single-session export.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9bc4602d-c3ea-47d6-9bc1-dc188181ff88
📒 Files selected for processing (1)
claude_code_log/converter.py
|
Hey, thanks a lot for this PR! What do you think about dropping the Session ids should be globally unique and now we have a SQLite cache, so it's a simple lookup. |
Hello, this is a PR to propose adding a
--session-idflag to allow exporting a single conversation by session ID.Sample usage:
Summary by CodeRabbit
New Features
Bug Fixes / Robustness
Tests