name: og-add-history description: Add current project's Claude Code conversation history to oGMemory
oGMemory Add History
Add current project's Claude Code historical conversations to oGMemory by calling /api/v1/after_turn for each transcript.
When to use
- User wants to import past conversations into memory
- User says "add history" or "import conversations"
- User types
/og-add-history
Instructions
Step 1: Estimate cost and confirm
Show the user a cost estimate for the current project:
python3 -c "
import os
cwd = os.environ.get('PWD', os.getcwd())
proj = cwd.replace('/', '-').replace('_', '-')
base = os.path.expanduser(f'~/.claude/projects/{proj}')
if not os.path.isdir(base):
base = os.path.expanduser(f'~/.claude/projects/-{proj}')
total_size = 0; total_files = 0; skipped = 0
if os.path.isdir(base):
for root, dirs, files in os.walk(base):
dirs[:] = [d for d in dirs if d != 'subagents']
for f in files:
if f.endswith('.jsonl') and not f.endswith('.ingest-offset'):
path = os.path.join(root, f)
off = path + '.ingest-offset'
if os.path.isfile(off):
try:
with open(off) as of:
if int(of.read().strip()) >= os.path.getsize(path):
skipped += 1; continue
except: pass
total_size += os.path.getsize(path); total_files += 1
print(f'Project: {proj}')
print(f'Transcripts: {total_files} (skipped {skipped} already ingested)')
print(f'Total size: {total_size / 1024 / 1024:.1f} MB')
print(f'Estimated tokens (embedding): ~{total_size // 4:,}')
print(f'LLM extraction calls: ~{total_files}')
print(f'Estimated time: ~{total_files * 3 // 60 + 1} minutes')
"
Ask the user to confirm before proceeding.
Step 2: Run batch add
For each transcript: read JSONL, extract messages (same parsing logic as call_after_turn.py), POST to /api/v1/after_turn.
python3 -c "
import os, json, urllib.request
cwd = os.environ.get('PWD', os.getcwd())
proj = cwd.replace('/', '-').replace('_', '-')
base = os.path.expanduser(f'~/.claude/projects/{proj}')
if not os.path.isdir(base): base = os.path.expanduser(f'~/.claude/projects/-{proj}')
OG_URL = os.environ.get('OG_MEMORY_URL', 'http://localhost:8090')
ok = skip = fail = dedup = 0
for root, dirs, files in os.walk(base):
dirs[:] = [d for d in dirs if d != 'subagents']
for f in sorted(files):
if not f.endswith('.jsonl') or f.endswith('.ingest-offset'): continue
path = os.path.join(root, f)
sid = f.replace('.jsonl', '')
off_path = path + '.ingest-offset'
if os.path.isfile(off_path):
try:
with open(off_path) as of:
if int(of.read().strip()) >= os.path.getsize(path):
print(f'DEDUP {sid}'); dedup += 1; continue
except: pass
msgs = []
for line in open(path, errors='replace'):
line = line.strip()
if not line: continue
try: e = json.loads(line)
except: continue
if e.get('isSidechain') or e.get('isApiErrorMessage'): continue
if e.get('type') not in ('user','assistant'): continue
m = e.get('message', {})
if m.get('role') not in ('user','assistant'): continue
c = m.get('content','')
t = c if isinstance(c,str) else '\n'.join(b.get('text','') for b in c if isinstance(b,dict) and b.get('type')=='text')
t = t.strip()
if t: msgs.append({'role':m['role'],'content':t})
if not msgs: print(f'SKIP {sid}'); skip += 1; continue
payload = json.dumps({'sessionId':sid,'messages':msgs,'accountId':os.environ.get('OG_MEMORY_ACCOUNT_ID','acct-demo'),'userId':os.environ.get('OG_MEMORY_USER_ID','u-claude'),'agentId':'claude-code','hook_event_name':'Stop'}).encode()
req = urllib.request.Request(f'{OG_URL}/api/v1/after_turn', data=payload, headers={'Content-Type':'application/json'}, method='POST')
try:
with urllib.request.urlopen(req, timeout=30) as resp:
if resp.status < 300:
print(f'OK {sid}: {len(msgs)} msgs'); ok += 1
with open(off_path,'w') as of: of.write(str(os.path.getsize(path)))
else: print(f'FAIL {sid}: {resp.status}'); fail += 1
except Exception as ex: print(f'FAIL {sid}: {ex}'); fail += 1
print(f'\nDone: ok={ok} fail={fail} skip={skip} dedup={dedup}')
"
Step 3: Report results
Report the counts and verify service health:
curl -s http://localhost:8090/api/v1/health
Important notes
- Background extraction/embedding continues after the POST returns
- Already-added sessions are skipped via
.ingest-offsetfiles - Subagent transcripts are automatically excluded
- By default only the current project's history is ingested