Compare commits

...

5 Commits

Author SHA1 Message Date
Alex Newman 35b7aab174 Release v3.6.10
Published from npm package build
Source: https://github.com/thedotmack/claude-mem-source
2025-09-16 20:20:56 -04:00
Alex Newman 2601215c91 Release v3.6.9
Published from npm package build
Source: https://github.com/thedotmack/claude-mem-source
2025-09-14 23:57:39 -04:00
Alex Newman 4ebf0cad6b Release v3.6.8
Published from npm package build
Source: https://github.com/thedotmack/claude-mem-source
2025-09-14 19:38:27 -04:00
Alex Newman 98d959112c Release v3.6.6
Published from npm package build
Source: https://github.com/thedotmack/claude-mem-source
2025-09-14 18:48:58 -04:00
Alex Newman d01c2afaa6 Release v3.6.5
Published from npm package build
Source: https://github.com/thedotmack/claude-mem-source
2025-09-14 14:36:54 -04:00
11 changed files with 248 additions and 137 deletions
+41
View File
@@ -5,6 +5,47 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [3.6.10] - 2025-09-16
### Added
- Claude Code statusline integration for real-time memory status
- MCP memory tools server providing compress, stats, search, and overview commands
- Concept documentation explaining memory compression and context loading
### Fixed
- Corrected integration architecture to use hooks instead of MCP SDK
## [3.6.9] - 2025-09-14
### Added
- Display current date and time at the top of session-start hook output for better temporal context
### Changed
- Enhanced session-start hook formatting with emoji icons and separator lines for improved readability
## [3.6.8] - 2025-09-14
### Fixed
- Fixed publish command failing when no version-related memories exist for changelog generation
## [3.6.6] - 2025-09-14
### Fixed
- Resolved compaction errors when processing large conversation histories by reducing chunk size limits to stay within Claude's context window
## [3.6.5] - 2025-09-14
### Changed
- Session groups now display in chronological order (most recent first)
### Fixed
- Improved CLI path detection for cross-platform compatibility
## [3.6.4] - 2025-09-13
### Changed
+2 -2
View File
@@ -3,5 +3,5 @@ allowed-tools: Bash
description: Write an overview and save with claude-mem
---
**Write an overview** of the current conversation context and:
1. **Add it to claude-mem** using the chroma MCP tools
2. **IMPORTANT! Save the overview to index** using the claude-mem CLI tool: `claude-mem save "your overview message"`
1. **Add it to claude-mem** using the chroma MCP tools. Always use primitive types (strings, numbers, booleans) when calling MCP Chroma tools directly. Arrays should be comma-separated strings, and nested objects should be flattened.
2. **Save the overview to index** using the claude-mem CLI tool: `claude-mem save "your overview message"`
+117 -115
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "claude-mem",
"version": "3.6.4",
"version": "3.6.10",
"description": "Memory compression system for Claude Code - persist context across sessions",
"keywords": [
"claude",
+28 -2
View File
@@ -393,8 +393,34 @@ Start searching now.` :
}
if (memories.length === 0) {
console.log('\n⚠️ No version-related memories found. Try compressing more sessions first.');
process.exit(1);
console.log('\n⚠️ No version-related memories found for this version.');
console.log(' This is normal for the first release or when no changes were tracked.');
console.log(' Creating a placeholder changelog entry...');
// Create a minimal placeholder entry
const placeholderEntry: ChangelogEntry = {
version: versionsToSearch[0], // Use the first (current) version
date: todayStr,
type: 'Changed',
description: 'Initial release or minor updates',
timestamp: new Date().toISOString(),
generatedAt: new Date().toISOString()
};
// Save the placeholder entry
if (!fs.existsSync(projectChangelogDir)) {
fs.mkdirSync(projectChangelogDir, { recursive: true });
}
const jsonlContent = JSON.stringify(placeholderEntry) + '\n';
fs.appendFileSync(changelogJsonlPath, jsonlContent);
console.log(`✅ Created placeholder changelog entry for v${versionsToSearch[0]}`);
// Generate the CHANGELOG.md with the placeholder
await updateChangelogFromJsonl(options);
return; // Exit successfully
}
console.log(`✅ Found ${memories.length} version-related memories\n`);
+5 -3
View File
@@ -1,7 +1,7 @@
import { OptionValues } from 'commander';
import { readFileSync, writeFileSync, existsSync, chmodSync, mkdirSync, copyFileSync, statSync, readdirSync } from 'fs';
import { join, resolve, dirname } from 'path';
import { homedir } from 'os';
import { homedir, platform } from 'os';
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';
import * as p from '@clack/prompts';
@@ -95,7 +95,8 @@ async function validatePrerequisites(): Promise<boolean> {
name: 'Claude Code CLI',
check: async () => {
try {
execSync('which claude', { stdio: 'ignore' });
const command = platform() === 'win32' ? 'where claude' : 'which claude';
execSync(command, { stdio: 'ignore' });
return { success: true, message: '' };
} catch {
return { success: false, message: 'Claude Code CLI not found. Please install: https://docs.anthropic.com/claude/docs/claude-code' };
@@ -184,7 +185,8 @@ async function validatePrerequisites(): Promise<boolean> {
// <Block> Claude binary path detection
function detectClaudePath(): string | null {
try {
const path = execSync('which claude', {
const command = platform() === 'win32' ? 'where claude' : 'which claude';
const path = execSync(command, {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'ignore']
}).trim();
+17 -10
View File
@@ -10,12 +10,6 @@ import {
outputSessionStartContent
} from '../prompts/templates/context/ContextTemplates.js';
interface IndexEntry {
summary: string;
entity: string;
keywords: string[];
}
interface TrashStatus {
folderCount: number;
fileCount: number;
@@ -23,6 +17,14 @@ interface TrashStatus {
isEmpty: boolean;
}
function buildProjectMatcher(projectName: string): (value?: string) => boolean {
const aliases = new Set<string>();
aliases.add(projectName);
aliases.add(projectName.replace(/-/g, '_'));
aliases.add(projectName.replace(/_/g, '-'));
return (value?: string) => !!value && aliases.has(value);
}
function formatSize(bytes: number): string {
if (bytes === 0) return '0 B';
const k = 1024;
@@ -115,20 +117,25 @@ export async function loadContext(options: OptionValues = {}): Promise<void> {
const sessions = jsonObjects.filter(obj => obj.type === 'session');
// Filter each type by project if specified
// Handle both hyphen and underscore formats since index has mixed entries
let filteredMemories = memories;
let filteredOverviews = overviews;
let filteredSessions = sessions;
if (options.project) {
filteredMemories = memories.filter(obj => obj.project === options.project);
filteredOverviews = overviews.filter(obj => obj.project === options.project);
const matchesProject = buildProjectMatcher(options.project);
filteredMemories = memories.filter(obj => matchesProject(obj.project));
filteredOverviews = overviews.filter(obj => matchesProject(obj.project));
filteredSessions = sessions.filter(obj => matchesProject(obj.project));
}
if (options.format === 'session-start') {
// Get last 10 memories and last 5 overviews for session-start
const recentMemories = filteredMemories.slice(-10);
const recentOverviews = filteredOverviews.slice(-5);
const recentSessions = filteredSessions.slice(-5);
// Combine them for the display
const recentObjects = [...recentMemories, ...recentOverviews];
const recentObjects = [...recentSessions, ...recentMemories, ...recentOverviews];
// Find most recent timestamp for last session info
let lastSessionTime = 'recently';
@@ -195,4 +202,4 @@ export async function loadContext(options: OptionValues = {}): Promise<void> {
console.log(createUserFriendlyError('Context loading', errorMessage, 'Check file permissions and try again'));
}
}
}
}
+5
View File
@@ -28,6 +28,11 @@ function generateSessionId(message: string): string {
* Save command - stores a message to both Chroma collection and JSONL index
*/
export async function save(message: string, options: OptionValues = {}): Promise<void> {
// Debug: Log what we receive
appendFileSync('/Users/alexnewman/.claude-mem/save-debug.log',
`[${new Date().toISOString()}] Received message: "${message}" (type: ${typeof message}, length: ${message?.length})\n`,
'utf8');
if (!message || message.trim() === '') {
console.error('Error: Message is required');
process.exit(1);
+2 -2
View File
@@ -34,8 +34,8 @@ export interface ChunkedMessage {
}
export class ChunkManager {
private static readonly DEFAULT_MAX_TOKENS = 28000;
private static readonly DEFAULT_MAX_BYTES = 98000;
private static readonly DEFAULT_MAX_TOKENS = 22400; // Reduced by 20% from 28000
private static readonly DEFAULT_MAX_BYTES = 78400; // Reduced by 20% from 98000
private static readonly DEFAULT_CONTEXT_OVERLAP = 2;
private static readonly CHARS_PER_TOKEN_ESTIMATE = 3.5;
+2 -2
View File
@@ -191,8 +191,8 @@ export class PromptOrchestrator {
projectName = this.projectName,
} = context;
// Extract project prefix from project name (convert to snake_case)
const projectPrefix = projectName.replace(/[-\s]/g, '_').toLowerCase();
// Use project name as-is for consistency with directory names
const projectPrefix = projectName;
// Use the simple prompt with the transcript included
return createAnalysisPrompt(
@@ -559,9 +559,29 @@ export function outputSessionStartContent(params: {
const { projectName, memoryCount, lastSessionTime, recentObjects } = params;
const width = getWrapWidth();
// Start with current date and time at the top
const now = new Date();
const dateTimeFormatted = now.toLocaleString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
timeZoneName: 'short',
});
console.log('');
console.log(wrapText(`📅 ${dateTimeFormatted}`, width));
console.log(makeLine('─', width));
// Extract overviews for user display - get more to show session grouping
const overviews = extractOverviews(recentObjects, 10, projectName);
// Debug: Log what we're getting
console.error(`[DEBUG] recentObjects has ${recentObjects.length} items`);
console.error(`[DEBUG] overviews extracted: ${overviews.length}`);
// Process memory entries for Claude context
const memories = processMemoryEntries(recentObjects);
// Helper to split and normalize keywords into a map (lowercased -> original)
@@ -613,6 +633,14 @@ export function outputSessionStartContent(params: {
// Overview section at bottom with session grouping
if (overviews.length > 0) {
const sessionGroups = groupOverviewsBySession(overviews);
// Sort groups by timestamp, oldest first for chronological reading order
sessionGroups.sort((a, b) => {
const timeA = a.earliestTimestamp?.getTime() || 0;
const timeB = b.earliestTimestamp?.getTime() || 0;
return timeA - timeB; // Ascending order (oldest first)
});
console.log('');
console.log(wrapText('🧠 Overviews', width));