feat: add save-trajectory skill to export conversation as OpenAI chat format#89
Conversation
… format Adds a new skill that saves the current Claude Code session's conversation history as a JSON file in OpenAI chat completion format. Trajectories are saved to .kaizen/trajectories/ for analysis and fine-tuning. Uses temp file approach for JSON transfer and runs in forked context to keep parent clean.
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds a new "Save Trajectory" skill: documentation plus a Python script that converts/validates trajectory JSON and persists timestamped trajectory files under a project-scoped Changes
Sequence Diagram(s)sequenceDiagram
autonumber
rect rgba(200,200,255,0.5)
participant Claude as Claude Session
end
rect rgba(200,255,200,0.5)
participant Skill as Save Trajectory Skill / Write Tool
end
rect rgba(255,200,200,0.5)
participant Script as save_trajectory.py
end
rect rgba(255,255,200,0.5)
participant FS as Filesystem (.kaizen/trajectories/)
end
Claude->>Skill: Trigger save (trajectory JSON)
Skill->>Script: Provide JSON (stdin / temp file)
Script->>Script: Validate JSON & messages[]
Script->>FS: Create trajectories dir (with secure perms)
Script->>FS: Write timestamped file (handle collisions)
Script->>Script: Log entry (KAIZEN_DEBUG -> temp log)
Script-->>Skill: Return saved filepath / status
Skill-->>Claude: Confirm save to user
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
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)
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.
🧹 Nitpick comments (2)
plugins/kaizen/skills/save-trajectory/scripts/save_trajectory.py (2)
39-39: Module-level side effect on import.This
log()call executes when the module is imported, not just when run as a script. While guarded byKAIZEN_DEBUG, consider moving it insidemain()for cleaner import behavior if this module might be imported elsewhere.♻️ Move log call into main()
-log("Script started") - - def get_trajectories_dir():Then at the start of
main():def main(): log("Script started") # Read trajectory JSON from file argument or stdin🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugins/kaizen/skills/save-trajectory/scripts/save_trajectory.py` at line 39, The module currently calls log("Script started") at import time (guarded by KAIZEN_DEBUG), causing a side effect on import; move that call into the start of the main() function so the message only logs when the script is executed (not merely imported). Locate the top-level log("Script started") invocation and remove it, then add a log("Script started") as the first line inside the existing main() function (preserving the KAIZEN_DEBUG guard if present) so initialization logging happens only during main() execution.
2-5: Docstring doesn't reflect file input capability.The docstring mentions only stdin, but the script also accepts a file path argument (line 74). Consider updating for accuracy.
📝 Suggested docstring update
""" Save Trajectory Script -Reads a trajectory JSON from stdin and writes it to the trajectories directory. +Reads a trajectory JSON from a file argument or stdin and writes it to the trajectories directory. """🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugins/kaizen/skills/save-trajectory/scripts/save_trajectory.py` around lines 2 - 5, Update the module docstring in save_trajectory.py to accurately state that the script can read a trajectory JSON either from stdin or from a provided file path argument (the CLI entrypoint/main function that checks for a file path argument), and mention the expected JSON format and that it writes to the trajectories directory; locate the top-of-file docstring and the argument-handling code in the main function to mirror its behavior (stdin or file path) in the description.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@plugins/kaizen/skills/save-trajectory/scripts/save_trajectory.py`:
- Line 39: The module currently calls log("Script started") at import time
(guarded by KAIZEN_DEBUG), causing a side effect on import; move that call into
the start of the main() function so the message only logs when the script is
executed (not merely imported). Locate the top-level log("Script started")
invocation and remove it, then add a log("Script started") as the first line
inside the existing main() function (preserving the KAIZEN_DEBUG guard if
present) so initialization logging happens only during main() execution.
- Around line 2-5: Update the module docstring in save_trajectory.py to
accurately state that the script can read a trajectory JSON either from stdin or
from a provided file path argument (the CLI entrypoint/main function that checks
for a file path argument), and mention the expected JSON format and that it
writes to the trajectories directory; locate the top-of-file docstring and the
argument-handling code in the main function to mirror its behavior (stdin or
file path) in the description.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 7e5d4c28-2caa-471e-9522-70fc9b79c10d
📒 Files selected for processing (2)
plugins/kaizen/skills/save-trajectory/SKILL.mdplugins/kaizen/skills/save-trajectory/scripts/save_trajectory.py
Lazy-init log directory to avoid module-level side effects, cap filename collision suffix at 1000, remove hardcoded model ID from SKILL.md, add explicit regex for system-reminder stripping, and document handling of compressed messages.
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
plugins/kaizen/skills/save-trajectory/SKILL.md (1)
141-143: Prefer.gitignoreas the default recommendation.These artifacts are whole-session exports and can easily include prompts, tool output, secrets, or PII. I’d document “gitignore by default, commit only intentionally” instead of presenting both options as equivalent.
📝 Suggested wording
-- Trajectories are saved per-project in `.kaizen/trajectories/` and can be version-controlled or gitignored as preferred. +- Trajectories are saved per-project in `.kaizen/trajectories/`. Add this directory to `.gitignore` by default unless you intentionally want to curate and review trajectory exports for version control.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plugins/kaizen/skills/save-trajectory/SKILL.md` around lines 141 - 143, The wording in SKILL.md currently presents committing trajectories and gitignoring them as equivalent; change the guidance to recommend gitignore by default and only commit trajectories intentionally by replacing the third bullet that mentions ".kaizen/trajectories/" with a clear recommendation: state that trajectories are saved under ".kaizen/trajectories/" and should be added to .gitignore by default because they may contain prompts, tool output, secrets or PII, and provide a short note on when it is acceptable to commit (e.g., after redaction or explicit review). Keep the mention that the format is compatible with OpenAI chat completions but make the default safety posture explicit.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@plugins/kaizen/skills/save-trajectory/scripts/save_trajectory.py`:
- Around line 42-51: The trajectories output is being created with default
permissions (in get_trajectories_dir and the file-write code at the later write
site around lines 106-108) which can be group/world-readable; update
get_trajectories_dir to create the directory with restrictive permissions (e.g.,
mode 0o700) and ensure the code that writes trajectory files (the save/write
routine around lines 106-108) creates files with restrictive permissions (e.g.,
0o600) — either by using os.open with an explicit mode or by calling Path.chmod
immediately after creation — so that both the .kaizen/trajectories directory and
individual trajectory files are owner-only accessible.
- Around line 33-39: The log() helper currently allows any exceptions from
_get_log_file() or file I/O to bubble up and abort execution when KAIZEN_DEBUG
is set; change log() to be best-effort by wrapping the call to _get_log_file()
and the open/write operations in a try/except that catches all exceptions (e.g.,
Exception) and silently returns on failure (optionally logging to stderr), so
debug logging never raises and does not alter functional behavior of main();
keep the KAIZEN_DEBUG guard and the timestamp/message formatting but ensure any
error in log() is swallowed.
- Around line 75-96: Validate that the parsed trajectory is a dict before
accessing methods like .keys() or .get(): after json.load (from file or
sys.stdin) check isinstance(trajectory, dict) and if not, log and print an error
to stderr (e.g., "Error: Expected JSON object with top-level keys, got <type>")
and sys.exit(1). Expand the existing exception handling around the
open/json.load logic to catch OSError (and optionally PermissionError) in
addition to FileNotFoundError and json.JSONDecodeError, normalize those into
CLI-friendly messages (use print(..., file=sys.stderr) and log(...)) and exit
non-zero; ensure references include input_path, trajectory, messages, log,
json.load so you update the try/except surrounding that block. Ensure messages =
trajectory.get("messages", []) only runs after the trajectory type check.
In `@plugins/kaizen/skills/save-trajectory/SKILL.md`:
- Around line 117-121: Replace the current single-line command that relies on
"&& rm -f .kaizen/tmp/trajectory_input.json" with a pattern that assigns the
temp path to a variable (e.g., tmp=.kaizen/tmp/trajectory_input.json), ensures
the directory exists with mkdir -p, registers a trap to remove "$tmp" on EXIT,
and then invokes the script with the quoted "$tmp" argument (python3
${CLAUDE_PLUGIN_ROOT}/skills/save-trajectory/scripts/save_trajectory.py "$tmp")
so the temp file is always cleaned up even if the script or writes fail; ensure
the trap uses rm -f and the temp variable is quoted when passed to the script.
---
Nitpick comments:
In `@plugins/kaizen/skills/save-trajectory/SKILL.md`:
- Around line 141-143: The wording in SKILL.md currently presents committing
trajectories and gitignoring them as equivalent; change the guidance to
recommend gitignore by default and only commit trajectories intentionally by
replacing the third bullet that mentions ".kaizen/trajectories/" with a clear
recommendation: state that trajectories are saved under ".kaizen/trajectories/"
and should be added to .gitignore by default because they may contain prompts,
tool output, secrets or PII, and provide a short note on when it is acceptable
to commit (e.g., after redaction or explicit review). Keep the mention that the
format is compatible with OpenAI chat completions but make the default safety
posture explicit.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 04a89409-0c33-4e0e-ae89-4eb109baf4a1
📒 Files selected for processing (2)
plugins/kaizen/skills/save-trajectory/SKILL.mdplugins/kaizen/skills/save-trajectory/scripts/save_trajectory.py
…rashes the script
Document the save-trajectory skill in the Skills Included section and update the Plugin Structure directory tree.
|
The build failures don't seem related to this PR. |
|
|
||
| ## Overview | ||
|
|
||
| This skill saves the current Claude Code session's conversation history as a JSON file in OpenAI chat completion format. The trajectory is saved to `.kaizen/trajectories/` in the project root. This enables trajectory analysis, fine-tuning data collection, and session review. |
There was a problem hiding this comment.
I know it's specifically a claude code skill, but if this is a standardized format maybe we shouldn't name Claude
Adds a new skill that saves the current Claude Code session's conversation history as a JSON file in OpenAI chat completion format. Trajectories are saved to .kaizen/trajectories/ for analysis and fine-tuning. Uses temp file approach for JSON transfer and runs in forked context to keep parent clean.
May be useful for #88 and other debugging tasks.
Summary by CodeRabbit
New Features
Documentation