remem-ai 0.4.4

Persistent memory for Claude Code — single binary, zero subprocesses
Documentation
use anyhow::Result;
use rusqlite::params;

use crate::context::claude_memory::index::ensure_memory_index;
use crate::context::claude_memory::paths::claude_memory_dir;
use crate::context::claude_memory::render::{
    max_sessions, render_memory_content, SessionRow, REMEM_FILE,
};

pub fn sync_to_claude_memory(cwd: &str, project: &str) -> Result<()> {
    let conn = crate::db::open_db()?;
    let memory_dir = claude_memory_dir(cwd);

    if !memory_dir.exists() {
        crate::log::info(
            "claude-mem",
            &format!("skip: no claude memory dir for {}", project),
        );
        return Ok(());
    }

    let sessions = load_recent_sessions(&conn, project)?;
    let Some(content) = render_memory_content(&sessions) else {
        return Ok(());
    };

    let file_path = memory_dir.join(REMEM_FILE);
    std::fs::write(&file_path, &content)?;
    ensure_memory_index(&memory_dir)?;

    let decisions_count = content.matches("\n- ").count();
    crate::log::info(
        "claude-mem",
        &format!(
            "synced {} sessions + {} decisions to {}",
            sessions.len(),
            decisions_count,
            file_path.display()
        ),
    );

    Ok(())
}

fn load_recent_sessions(conn: &rusqlite::Connection, project: &str) -> Result<Vec<SessionRow>> {
    let mut stmt = conn.prepare(
        "SELECT request, completed, decisions, created_at_epoch \
         FROM session_summaries \
         WHERE project = ?1 AND request IS NOT NULL AND request != '' \
         ORDER BY created_at_epoch DESC LIMIT ?2",
    )?;

    let rows = stmt.query_map(params![project, max_sessions() as i64], |row| {
        Ok(SessionRow {
            request: row.get(0)?,
            completed: row.get(1)?,
            decisions: row.get(2)?,
            created_at_epoch: row.get(3)?,
        })
    })?;

    let mut sessions = Vec::new();
    for row in rows {
        sessions.push(row?);
    }
    Ok(sessions)
}