From ctx
Imports unimported sessions into journal and batch-enriches all unenriched entries. Use to process journal backlog or on 'process the journal' requests.
npx claudepluginhub activememory/ctx --plugin ctxThis skill is limited to using the following tools:
Full journal pipeline: import if needed, then batch-enrich.
Enriches session journal entries with YAML frontmatter (title, type, outcome, topics, technologies, libraries, key files) for searchability when lacking metadata.
Enriches hermit/Cortex Markdown files with frontmatter (title, created) and tags. Scans sessions, proposals, artifacts for gaps; clusters similar files for batch confirmation before writes.
Share bugs, ideas, or general feedback.
Full journal pipeline: import if needed, then batch-enrich.
check-journal hook reports unimported or unenriched entries/ctx-journal-enrich instead)Before enriching, check whether there are unimported sessions. If
the journal directory has no .md files at all, or if there are
.jsonl session files newer than the newest journal entry, import
them first.
CTX_DIR=$(ctx system bootstrap -q)
JOURNAL_DIR="$CTX_DIR/journal"
# Check if any .md files exist
md_count=$(ls "$JOURNAL_DIR"/*.md 2>/dev/null | wc -l)
if [ "$md_count" -eq 0 ]; then
echo "No journal entries found: importing all sessions."
ctx journal import --all --yes
else
# Compare newest .md mtime against .jsonl files
newest_md=$(stat -c %Y $(ls -t "$JOURNAL_DIR"/*.md | head -1))
unimported=$(find ~/.claude/projects -name "*.jsonl" -newermt @${newest_md} 2>/dev/null | wc -l)
if [ "$unimported" -gt 0 ]; then
echo "$unimported unimported session(s) found: importing first."
ctx journal import --all --yes
fi
fi
Report how many sessions were imported (or "none needed") before moving to enrichment.
List all journal entries that lack enrichment using the state file:
# List .md files in journal dir and check state
CTX_DIR=$(ctx system bootstrap -q)
for f in "$CTX_DIR/journal/"*.md; do
name=$(basename "$f")
ctx system mark-journal --check "$name" enriched || echo "$f"
done
Or read .state.json in the journal directory directly and list
entries without an enriched date set.
If mark-journal --check is unavailable (no state file, command
fails), fall back to frontmatter inspection. An entry is considered
already enriched if its YAML frontmatter contains both type
and outcome fields: these are set exclusively by enrichment, never
by import.
Do NOT use title or date to detect enrichment: those are always
present from import. The enrichment-only fields are:
| Field | Set by |
|---|---|
title | Import |
date | Import |
time | Import |
model | Import |
tokens_in | Import |
tokens_out | Import |
session_id | Import |
project | Import |
type | Enrichment |
outcome | Enrichment |
topics | Enrichment |
technologies | Enrichment |
summary | Enrichment |
If all entries already have enrichment recorded, report that and stop.
Skip entries that are not worth enriching:
.state.json has a
locked date OR the frontmatter contains locked: true. Never
modify locked files: neither metadata nor body. Check via:
ctx system mark-journal --check <filename> locked
or look for locked: true in the YAML frontmatter.wc -l <file>
-p2.md, -p3.md
etc. Enrich only the first part; continuation parts inherit
the frontmatter topic.Report how many entries will be processed and how many were filtered out.
For each entry, read the conversation and extract:
Apply YAML frontmatter to each file:
---
title: "Session title"
date: 2026-01-27
type: feature
outcome: completed
topics:
- authentication
- caching
technologies:
- go
- redis
---
After writing frontmatter to each file, update the state file:
ctx system mark-journal <filename> enriched
After processing, report:
ctx journal site --buildInteractive (default when user is present): show a summary of proposed enrichments before applying. Group by type/outcome so the user can scan quickly rather than reviewing one by one.
Unattended (when running in a loop or explicitly told "just do it"): apply enrichments directly and report results.
For large backlogs, use the heuristic enrichment script bundled
in references/enrich-heuristic.py. This script infers type,
outcome, topics, and technologies from the title and filename
patterns, then inserts frontmatter and marks state automatically.
Build a file list of eligible entries (non-multipart, 20+ lines,
missing type: and outcome: fields):
CTX_DIR=$(ctx system bootstrap -q)
for f in "$CTX_DIR"/journal/*.md; do
[ -f "$f" ] || continue
has_type=$(head -30 "$f" | grep -c '^type:' || true)
has_outcome=$(head -30 "$f" | grep -c '^outcome:' || true)
if [ "$has_type" -eq 0 ] || [ "$has_outcome" -eq 0 ]; then
name=$(basename "$f")
case "$name" in *-p[0-9].md|*-p[0-9][0-9].md) continue ;; esac
lines=$(wc -l < "$f")
[ "$lines" -ge 20 ] && echo "$f"
fi
done > /tmp/enrich-list.txt
Run the heuristic enrichment script. The script path is relative to this skill's directory: copy it to /tmp or reference it via the full embedded path:
python3 references/enrich-heuristic.py /tmp/enrich-list.txt
The script handles everything: reads files, inserts frontmatter,
runs ctx system mark-journal for each, and reports counts.
| Backlog size | Approach |
|---|---|
| 1-5 entries | Read each file, enrich manually with full context |
| 6-20 entries | Sequential processing in the main conversation |
| 20+ entries | Use enrich-heuristic.py for bulk processing |
The heuristic script produces good-enough enrichment from titles and filenames. For higher quality, follow up with manual review of entries where the type or topics look wrong.
Subagent parallelization is an alternative for 20+ entries, but requires that subagents have Edit and Bash permissions granted. If permissions are restricted, the heuristic script is faster and more reliable.