Skip to content
cccskills
FreePublished on GitHub

session-save

Save current Codex session to 2ndBrain vault with frontmatter, executive brief, and full transcript

The English summary is being prepared. Showing the original description.

See how to install

Files included (2)

  • SKILL.md7.5 KB
  • agents/openai.yaml43 B

SKILL.md (original)

Review the instructions the agent will receive before you install.

session-save

Use this skill when the user asks to run the migrated command session-save or invokes $session-save.

Command Template

Save Session to 2ndBrain

Saves the current Codex session as a note in ~/2ndBrain/Codex-sessions/<year>/.

The note structure:

  1. YAML frontmatter — date, hostname, session name, cwd, git branch, token counts
  2. Executive brief — 3–5 bullet summary of what was done, key decisions, and open items
  3. --- separator
  4. Full session transcript — formatted as **User**: ... / **Codex**: ... blocks with tool calls noted inline

Step 1: Gather Environment Metadata

session_date=$(date +%Y-%m-%d)
session_time=$(date +%H:%M:%S)
session_year=$(date +%Y)
host=$(hostname -s)
cwd=$(pwd)
echo "date=${session_date} time=${session_time} host=${host} cwd=${cwd} year=${session_year}"

Step 2: Find Current Session File

encoded_cwd=$(pwd | sed 's|/|-|g')
project_dir="$HOME/.Codex/projects/${encoded_cwd}"
session_file=$(ls -t "${project_dir}"/*.jsonl 2>/dev/null | head -1)
if [ -z "$session_file" ]; then
  echo "ERROR: No session file found in ${project_dir}" >&2
  exit 1
fi
echo "session_file=${session_file}"

Step 3: Parse Session File

Run this Python script to extract all session data:

python3 << 'PYEOF'
import json, sys, os, subprocess, glob

cwd = subprocess.check_output(['pwd']).decode().strip()
encoded = cwd.replace('/', '-')
home = os.path.expanduser('~')
project_dir = f"{home}/.Codex/projects/{encoded}"
files = sorted(glob.glob(f"{project_dir}/*.jsonl"), key=os.path.getmtime, reverse=True)
session_file = files[0] if files else ''

if not session_file:
    print(json.dumps({'error': 'No session file found'}))
    sys.exit(1)

messages = []
total_output_tokens = 0
last_input_tokens = 0
session_id = None
ai_title = None
git_branch = None
session_cwd = None

with open(session_file) as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        try:
            entry = json.loads(line)
        except json.JSONDecodeError:
            continue

        if not session_id:
            session_id = entry.get('sessionId')
        if not git_branch and 'gitBranch' in entry:
            git_branch = entry['gitBranch']
        if not session_cwd and 'cwd' in entry:
            session_cwd = entry['cwd']

        # Grab latest ai-title
        if entry.get('type') == 'ai-title':
            ai_title = entry.get('aiTitle')
            continue

        entry_type = entry.get('type')
        if entry_type not in ('user', 'assistant'):
            continue

        # Skip meta/system user turns (isMeta = true with no real content)
        is_meta = entry.get('isMeta', False)
        msg = entry.get('message', {})
        if not isinstance(msg, dict):
            continue

        role = msg.get('role', entry_type)
        raw_content = msg.get('content', '')

        # Parse content blocks into text
        parts = []
        if isinstance(raw_content, list):
            for block in raw_content:
                if not isinstance(block, dict):
                    continue
                btype = block.get('type')
                if btype == 'text':
                    text = block.get('text', '').strip()
                    if text:
                        parts.append(text)
                elif btype == 'tool_use':
                    name = block.get('name', 'unknown')
                    inp = block.get('input', {})
                    # Summarize key input fields
                    summary_keys = ['command', 'path', 'file_path', 'query', 'skill', 'description']
                    detail = next((str(inp[k])[:120] for k in summary_keys if k in inp), '')
                    if detail:
                        parts.append(f'[→ {name}: {detail}]')
                    else:
                        parts.append(f'[→ {name}]')
                elif btype == 'tool_result':
                    pass  # omit tool results from transcript
        elif isinstance(raw_content, str):
            if raw_content.strip():
                parts.append(raw_content.strip())

        content = '\n'.join(parts).strip()
        if not content:
            continue

        # Skip purely-meta user turns (no actual user text, just system context)
        if is_meta and role == 'user' and not any(p for p in parts if not p.startswith('[')):
            continue

        messages.append({'role': role, 'content': content})

        # Token accounting
        usage = msg.get('usage', {})
        out = usage.get('output_tokens', 0)
        inp_total = (usage.get('input_tokens', 0)
                     + usage.get('cache_creation_input_tokens', 0)
                     + usage.get('cache_read_input_tokens', 0))
        if out:
            total_output_tokens += out
        if inp_total:
            last_input_tokens = inp_total

print(json.dumps({
    'session_id': session_id,
    'ai_title': ai_title,
    'git_branch': git_branch,
    'session_cwd': session_cwd,
    'total_output_tokens': total_output_tokens,
    'last_input_tokens': last_input_tokens,
    'total_tokens': last_input_tokens + total_output_tokens,
    'message_count': len(messages),
    'messages': messages,
}, ensure_ascii=False))
PYEOF

Capture the JSON output from this script. If it contains "error", report the error and stop.

Step 4: Generate Executive Brief

Read the messages array from the parsed JSON. Based on the full conversation content, write a concise executive brief:

  • 3–5 bullet points covering: what was investigated/built, key decisions made, commands run or files changed, and any open items or next steps
  • Tone: factual, past-tense, no filler ("we looked at", "the user asked" — just state what happened)
  • Each bullet should be one sentence

Example format:

- Audited the obsidian-skills plugin and three work commands that reference ~/2ndBrain/daily-notes.
- Discovered the JSONL session format includes an ai-title field, session_id, cwd, gitBranch, and per-message usage stats.
- Designed and wrote the /session-save command to ~/2ndBrain/Codex-sessions/.

Step 5: Determine Output Path

Use the ai_title from Step 3 (or "Untitled Session" if absent). Sanitize it for use as a filename: replace /, :, | with -; collapse spaces.

vault=~/2ndBrain
out_dir="${vault}/Codex-sessions/${session_year}"
filename="${session_date} ${ai_title}.md"
out_path="${out_dir}/${filename}"

Ensure the directory exists:

mkdir -p "${out_dir}"

Step 6: Format and Write the Note

Use the Write tool to create ${out_path} with this structure:

---
date: <YYYY-MM-DD>
time: <HH:MM:SS>
hostname: <host>
session: <ai_title>
session_id: <session_id>
cwd: <session_cwd>
branch: <git_branch>
tokens:
  output: <total_output_tokens>
  context: <last_input_tokens>
  total: <total_tokens>
messages: <message_count>
tags:
  - Codex-session
---

## Executive Brief

<bullet points from Step 4>

---

## Session Transcript

<for each message in order:>

**User**

<content>

---

**Codex**

<content>

---

<repeat for all messages>

Separate each message with ---. Keep the full content of each message — do not truncate.

Step 7: Report

Output a one-line confirmation:

Session saved: ~/2ndBrain/Codex-sessions/<year>/<filename>
Tokens: <last_input_tokens> context / <total_output_tokens> output / <total_tokens> total | Messages: <message_count>

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Quick-save the last assistant response as a verbatim note in the 2ndBrain Obsidian vault (~/2ndBrain/quick-notes/<year>/). Use when the user asks to quick-save/save the last response to 2ndBrain, or invokes $2ndbrain or /skill:2ndbrain.

The English summary is being prepared. Showing the original description.

phatblat/dotfiles12Updated Oct 19, 2026

Write commit messages under the agent-commits convention - a Conventional Commits fork with no chore catch-all, intent-only type tokens, facts in trailers, and legally-grounded AI provenance (Assisted-by, never Co-authored-by). Use when composing a commit in a repo whose commitlint.config.js extends agent-commits, when deciding between feat/fix/refactor/perf, or when recording AI participation.

The English summary is being prepared. Showing the original description.

phatblat/dotfiles12Updated Oct 19, 2026

Coordinate multi-agent work through durable artifacts in git instead of chat. Use this whenever a task involves sending a message to another agent, agent mailboxes or handoffs, claiming work from a shared queue, notifying another agent or crew (OpenClaw, Grok Bot, Claude Code, Codex, Gas Town/Gas City workers) that work is ready, or whenever the user mentions the artifact bus, message bus, agent mail, beads mail, doorbells, or pings between agents — even if they don't say "bus" explicitly.

The English summary is being prepared. Showing the original description.

phatblat/dotfiles12Updated Oct 19, 2026

aven

Free

Use aven to find tasks, update status, and leave durable handoff context.

The English summary is being prepared. Showing the original description.

phatblat/dotfiles12Updated Oct 19, 2026

Plan, order and deliver a batch of backlog items (e.g. every High item) in a Conventional Docs repo, one decision, branch, worktree, draft PR, review and merge per item. Use when asked to work through the backlog, implement all items of a priority, or sequence several backlog items end to end.

The English summary is being prepared. Showing the original description.

phatblat/dotfiles12Updated Oct 19, 2026

boris

Free

Codex workflow tips from Boris Cherny (creator of Codex) and the Codex team. Use when: setting up Codex, optimizing workflows, running parallel sessions, configuring AGENTS.md, using skills/commands, subagents, hooks, MCP integrations, or learning best practices. Covers: git worktrees, plan mode, verification, permissions, Slack MCP, BigQuery, prompting tips, plugins, custom agents, sandboxing, keybindings, status lines, output styles, customization, /simplify for code quality, /batch for parallel code migrations, /loop for scheduled tasks, code review agents, /btw for mid-task questions, /effort max reasoning, remote control sessions, voice mode, setup scripts, session naming, /color, PostCompact hook, auto mode, /schedule cloud jobs, iMessage plugin, auto-memory, and auto-dream, mobile app, session teleporting, Cowork Dispatch, Chrome extension, Desktop app, /branch forking, --bare SDK startup, --add-dir multi-repo, --agent custom agents, /voice input.

The English summary is being prepared. Showing the original description.

phatblat/dotfiles12Updated Oct 19, 2026

See all skills by phatblat

Report a problem with this skill