agent-environment-retr…
Use when a completed session needs an agent-environment retrospective. Not for an engineering retrospective from telemetry: use engineering-retrospective.
Use when the user asks to view, export, or inspect a session transcript in a browser. Not for sharing a session: use session-share.
$ npx -y skills add OutlineDriven/odin-claude-plugin --skill session-viewer --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/session-viewerContext preview
The summary Claude sees to decide when to auto-load this skill.
Use when the user asks to view, export, or inspect a session transcript in a browser. Not for sharing a session: use session-share.
name: session-viewer description: 'Use when the user asks to view, export, or inspect a session transcript in a browser. Not for sharing a session: use session-share.'
| Field | Bound contract | |---|---| | Trigger | User asks to view, export, inspect, or share a Codex, Claude Code, OpenClaw, or Pi session transcript in a browser. | | Authority | Reversible local: writes only the single HTML viewer file and one disposable generator script in the system temp directory; rollback is undo. No remote mutation. Never modifies the session file. | | Side effect | A single-file searchable HTML viewer embedding the (optionally raw) session JSONL is produced; it is opened in a browser only when the user asked to view it or passed `--open`. | | Done | HTML file is generated; session is correctly detected and normalized; tool output is searchable; private/credential content is not exposed. The file opens in a browser only when the user passed `--open` or explicitly asked to view it. |
1. Validate the input path at the trust boundary before any mutation: the file must exist, be non-empty, and be at most 256 MiB; otherwise stop with no writes. **Done when:** the path is validated or the stop is reported. 2. Fix the privacy mode before writing: default mode embeds a normalized, credential-scrubbed projection. Embed raw lines only when the user explicitly opts in with `--raw`; raw mode changes fidelity, never the scrub or the local-only boundary. **Done when:** the privacy mode is fixed. 3. Write the generator script below exactly as given to a scratch file in the system temp directory (for example `/tmp/session_viewer_gen.py`). It uses only the Python 3 standard library. Do not edit it. **Done when:** the scratch script is written. 4. Run `python3 <scratch> <session.jsonl>` with any optional flags. The script detects the format from structural signatures with a path-hint tiebreak, parses the JSONL line by line, and normalizes each line into unified records (index, timestamp, kind: user, assistant, system, summary, thinking, tool-call, tool-result, other; role, tool name, text). It scrubs credential-shaped strings (sk- tokens, ghp_ tokens, AKIA keys, xox tokens, bearer headers, key/token/password assignments). It renders one self-contained HTML viewer with an embedded JSON payload, substring search across message text, tool names, roles, and tool output, role filter chips, collapsible raw lines in raw mode, a metadata header, no external assets, and no network access. Every record is rendered through textContent so session content cannot inject markup. **Done when:** the HTML viewer is generated and the script report is captured. 5. Read the script report: format and how it was chosen, line, record, and skipped counts, masked-string count, raw mode, output path, and size. To prove the done predicate, open the file when the user asked to view it (or run with `--open`) and confirm it renders and that searching returns tool output. **Done when:** the report is read and the done predicate is proven or disproven. 6. Delete the scratch script. The HTML file is the only remaining artifact; deleting it is the complete rollback. **Done when:** the scratch script is deleted and only the HTML file remains.
#!/usr/bin/env python3
"""Generate a single-file searchable HTML viewer from an agent session JSONL.
Supported session formats: claude, codex, pi, openclaw.
Usage:
python3 session_viewer_gen.py SESSION.jsonl [--format auto|claude|codex|pi|openclaw]
[--out PATH] [--raw] [--open]
Exit codes: 0 success, 2 input or parse failure, 3 ambiguous format.
Standard library only; no network access.
"""
import argparse
import html
import json
import re
import sys
import webbrowser
from datetime import datetime, timezone
from pathlib import Path
FORMATS = ("claude", "codex", "pi", "openclaw")
MAX_INPUT_BYTES = 256 * 1024 * 1024
MASK = "[redacted]"
SCRUBBERS = (
(re.compile(r"\bsk-[A-Za-z0-9_-]{16,}"), MASK),
(re.compile(r"\bgh[pousr]_[A-Za-z0-9]{20,}"), MASK),
(re.compile(r"\bAKIA[0-9A-Z]{16}\b"), MASK),
(re.compile(r"\bxox[baprs]-[A-Za-z0-9-]{10,}"), MASK),
(re.compile(r"(?i)authorization[\s\"':=]+bearer\s+\S{16,}"), MASK),
(re.compile(r"(?i)\b(?:api[_-]?key|secret|token|password)[\"'\s:=]{1,4}\S{16,}"), MASK),
)
masked_hits = [0]
def scrub(text):
if not isinstance(text, str):
return text
for pattern, replacement in SCRUBBERS:
text, count = pattern.subn(replacement, text)
masked_hits[0] += count
return text
def record(index, kind, role, text, tool="", ts="", raw=None):
return {
"i": index,
"kind": kind,
"role": role,
"tool": tool,
"ts": ts,
"text": scrub(text) if isinstance(text, str) else "",
"raw": raw,
}
def text_of(content):
if isinstance(content, str):
return content
parts = []
if isinstance(content, list):
for block in content:
parts.append(text_of(block))
elif isinstance(content, dict):
for key in ("text", "thinking", "input_text", "output_text", "summary_text", "query", "content", "output"):
if key in content:
parts.append(text_of(content[key]))
elif content is not None:
parts.append(str(content))
return chr(10).join(part foFormerly the ODIN Claude Plugin. The repository URL is unchanged. Outline-Driven Development, nicknamed ODIN, is a highly opinionated code-agent skill library: principles-first engineering, surgical editing, and workflow automation, published as installable
Repo: OutlineDriven/odin-claude-plugin
Use when a completed session needs an agent-environment retrospective. Not for an engineering retrospective from telemetry: use engineering-retrospective.
Use when a repo needs agent setup, AGENTS.md added or made lean, CLAUDE.md audited, or agent instructions scored or pruned. Not for remote, credential,…
Use when a human explicitly asks for a full repository agent-compatibility pass returning a scored report with prioritized fixes. Not for tasks that require…
Use when setting up a project, auditing agent command permissions, or asking which read-only bash commands and domains to allow. Not for remote, credential,…
Use when asked to build or review a CLI intended for coding agents and return flag-driven, pipeline-safe, idempotent design advice. Not for running or…
Use when the user asks to make the skills framework work in a new harness, IDE, or CLI. Not for remote, credential, publish, deploy, or irreversible changes.