From copilot-cli-toolkit
Migrates markdown session logs to JSON format via Python scripts. Use for PRs with markdown logs needing schema conversion or batch-migrating historical sessions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/copilot-cli-toolkit:session-migrationclaude-sonnet-4-6The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Converts markdown session logs to JSON format for deterministic validation.
Converts markdown session logs to JSON format for deterministic validation.
# Migrate single file
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py ".agents/sessions/2026-01-09-session-385.md"
# Migrate all sessions in directory
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py ".agents/sessions/"
# Dry run to preview changes
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py ".agents/sessions/" --dry-run
# Force overwrite existing JSON
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py ".agents/sessions/" --force
Use this skill when:
migrate session logs - Convert markdown to JSONconvert sessions to JSON - Format migrationPR has old markdown sessions - In-flight PR migrationsession validation failing - Regex issues with markdown formatbatch migrate sessions - Historical log conversionUse this skill when:
Use session-init instead when:
Use session-log-fixer instead when:
Markdown session logs required fragile regex patterns to validate:
**Branch**: vs Branch: vs Starting Branch:JSON provides:
JSON sessions follow the schema at:
.agents/schemas/session-log.schema.json
JSON sessions are validated by:
scripts/validate_session_json.py
┌─────────────────────────────────────────────────────────┐
│ 1. INPUT │
│ Markdown session log (.md) │
│ OR directory of .md files │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 2. PARSE │
│ • Extract session number from filename │
│ • Extract date from filename │
│ • Find branch, commit, objective in content │
│ • Parse checklist tables for completion status │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 3. TRANSFORM │
│ • Build session object (number, date, branch, etc.) │
│ • Build protocolCompliance object │
│ • Map checkbox [x] to complete: true │
│ • Extract evidence from table cells │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 4. OUTPUT │
│ Write .json file alongside .md │
│ (same name, different extension) │
└─────────────────────────────────────────────────────────┘
{
"session": {
"number": 385,
"date": "2026-01-09",
"branch": "feat/session-init-skill",
"startingCommit": "abc1234",
"objective": "Session protocol validation improvements"
},
"protocolCompliance": {
"sessionStart": {
"serenaActivated": { "level": "MUST", "complete": true, "evidence": "Tool output" },
"handoffRead": { "level": "MUST", "complete": true, "evidence": "Content in context" }
},
"sessionEnd": {
"checklistComplete": { "level": "MUST", "complete": true, "evidence": "All [x] checked" },
"validationPassed": { "level": "MUST", "complete": true, "evidence": "Exit code 0" }
}
},
"workLog": [],
"endingCommit": "",
"nextSteps": []
}
| Parameter | Type | Required | Description |
|---|---|---|---|
-Path | string | Yes | Path to .md file or directory |
-Force | switch | No | Overwrite existing .json files |
-DryRun | switch | No | Preview without writing files |
The script returns an array of migrated file paths (string[]) and prints a summary:
=== Migration Summary ===
Migrated: 356
Skipped (JSON exists): 0
Failed: 0
| Code | Meaning | Action |
|---|---|---|
0 | Success | All files migrated or skipped (expected behavior) |
1 | Failure | One or more files failed migration (check error output) |
The script prints migration summary and returns exit code 0 on success, 1 on failure.
For PRs with in-flight markdown sessions:
Check for markdown sessions in PR:
git diff origin/main --name-only | grep -E '\.agents/sessions/.*\.md$'
Run migration:
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py ".agents/sessions/"
Validate migrated sessions:
for f in .agents/sessions/*.json; do python3 scripts/validate_session_json.py "$f"; done
Commit both formats (for transition period):
git add .agents/sessions/*.json
git commit -m "chore(session): migrate session logs to JSON format"
The migration script maps markdown checklist patterns to JSON keys.
| Regex Pattern | JSON Key | Level |
|---|---|---|
activate_project | serenaActivated | MUST |
initial_instructions | serenaInstructions | MUST |
HANDOFF\.md | handoffRead | MUST |
Create.*session.*log|session.*log.*exist|this.*file | sessionLogCreated | MUST |
skill.*script | skillScriptsListed | MUST |
usage-mandatory | usageMandatoryRead | MUST |
CONSTRAINTS | constraintsRead | MUST |
memor | memoriesLoaded | MUST |
verify.*branch|branch.*verif|declare.*branch | branchVerified | MUST |
not.*main|Confirm.*main | notOnMain | MUST |
git.*status | gitStatusVerified | SHOULD |
starting.*commit|Note.*commit | startingCommitNoted | SHOULD |
| Regex Pattern | JSON Key | Level |
|---|---|---|
Complete.*session.*log|session.*log.*complete|all.*section | checklistComplete | MUST |
HANDOFF.*read-only|Update.*HANDOFF | handoffPreserved | MUST |
Serena.*memory|Update.*memory|memory.*updat | serenaMemoryUpdated | MUST |
markdownlint|markdown.*lint|Run.*lint | markdownLintRun | MUST |
Commit.*change|change.*commit | changesCommitted | MUST |
Validate.*Session|validation.*pass|Route.*qa | validationPassed | MUST |
PROJECT-PLAN|task.*checkbox | tasksUpdated | SHOULD |
retrospective | retrospectiveInvoked | SHOULD |
| Avoid | Why | Instead |
|---|---|---|
| Manually converting markdown to JSON | Error-prone, misses edge cases | Use convert_session_to_json.py script |
| Deleting markdown files after migration | May need originals for reference | Keep both during transition period |
| Skipping validation after migration | Migrated JSON may still be incomplete | Always validate with validate_session_json.py |
Migrating without -DryRun first | Cannot preview changes | Use -DryRun to preview, then run for real |
After migration:
validate_session_json.pyUse -Force to overwrite:
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py ".agents/sessions/" --force
Expected for genuinely incomplete sessions. The migration preserves the actual state of checkboxes. Review failed sessions manually.
If a checklist item isn't detected, the markdown format may be non-standard. The script uses flexible regex but edge cases exist. Update the _find_checklist_item function patterns if needed.
Converts markdown session logs to JSON format.
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py <input-file> [--output <output-file>]
| Skill | Purpose |
|---|---|
| session-init | Create new sessions in JSON format |
| session-log-fixer | Fix validation failures |
| Resource | Location | Purpose |
|---|---|---|
| JSON Schema | .agents/schemas/session-log.schema.json | Defines required structure |
| JSON Validator | scripts/validate_session_json.py | Validates migrated JSON files |
| Legacy Validator | scripts/validate_session_json.py | Validates markdown (deprecated) |
npx claudepluginhub rjmurillo/ai-agentsMigrates markdown session logs to JSON format for deterministic validation. Use for PRs with old markdown sessions or batch-migrating historical logs.
Creates protocol-compliant JSON session logs with git-derived state, auto-incremented numbers, and validation enforcement. Use when starting new sessions to ensure CI compliance.
Converts Claude Code JSONL conversation logs into Markdown with project-aware indexing and retrospective analysis guidance. Supports incremental or full re-conversion by project.