Contribute effectively to claude-mem by fixing bugs, adding features, or improving documentation.

Project Overview

TypeScript CLI tool providing persistent memory for Claude Code sessions:
  • Session Compression: Converts conversation transcripts into structured memories
  • Context Loading: Retrieves relevant memories for new sessions
  • Vector Search: Uses ChromaDB for semantic memory retrieval
  • Claude Code Integration: Seamless hooks for automatic operation
  • Smart Trash System: Safe deletion with recovery capabilities

Development Environment Setup

1

Prerequisites

Required tools:
# Required
node --version  # >= 18.0.0
bun --version   # >= 1.0.0 (preferred) or npm

# Recommended
git --version
code --version  # VS Code or your preferred editor
Bun vs NPM: While the project works with both, Bun is preferred for development due to faster installation and builds.
2

Clone and Setup

# Clone the repository
git clone https://github.com/thedotmack/claude-mem.git
cd claude-mem

# Install dependencies
bun install

# Verify setup
bun run dev --version
3

Build System

# Build minified bundle
bun run build

# Run in development mode
bun run dev status

# Build for npm distribution
bun run build:npm
4

Local Testing

# Link for local testing
bun link

# Use local version globally
bun link claude-mem

# Test local installation
claude-mem --version
claude-mem status

Project Structure

Understanding the codebase organization:
claude-mem/
├── src/                    # TypeScript source code
│   ├── bin/cli.ts         # Main CLI entry point
│   ├── commands/          # CLI command implementations
│   ├── core/              # Core business logic
│   ├── services/          # External service integrations
│   ├── prompts/templates/ # LLM prompt templates
│   └── shared/            # Utilities and constants
├── hooks/                 # Claude Code integration hooks
├── releases/npm-package/  # NPM distribution package
├── scripts/               # Build and deployment scripts
├── dist/                  # Compiled output
└── docs/                  # Documentation source

Key Directories Explained

Development Workflow

Making Changes

1

Create Feature Branch

git checkout -b feature/your-feature-name
# or
git checkout -b fix/issue-description
2

Development Cycle

# Make changes to TypeScript files
vim src/commands/your-feature.ts

# Test in development mode
bun run dev your-feature --test-flag

# Build and test minified version
bun run build
node dist/claude-mem.min.js your-feature --test-flag
3

Local Integration Testing

# Test with local Claude Code installation
bun run dev install --force
# Start Claude Code session to test integration

# Reset to clean state
bun run dev uninstall
4

Code Quality Checks

# Lint code
bun run lint

# Fix linting issues
bun run lint:fix

# Format code
bun run format

Testing Strategies

Common Development Tasks

Adding a New CLI Command

1

Create Command File

// src/commands/my-command.ts
import { OptionValues } from 'commander';

export async function myCommand(options: OptionValues = {}): Promise<void> {
  console.log('Executing my command');
  // Implementation
}
2

Register in CLI

// src/bin/cli.ts
import { myCommand } from '../commands/my-command.js';

program
  .command('my-command')
  .description('Description of my command')
  .option('--flag', 'Command flag')
  .action(myCommand);
3

Test and Build

# Test in development
bun run dev my-command --flag

# Build and test minified
bun run build
node dist/claude-mem.min.js my-command --flag

Modifying Memory Compression

The compression system uses LLM prompts to analyze transcripts:
1

Update Analysis Templates

// src/prompts/templates/AnalysisTemplates.ts
export function createEntityExtractionInstructions(projectPrefix: string): string {
  return `
    Extract technical entities from the conversation...
    Focus on: ${projectPrefix}-specific patterns...
  `;
}
2

Modify Compression Logic

// src/core/compression/TranscriptCompressor.ts
async compress(transcript: any): Promise<CompressionResult> {
  // Update compression algorithm
  const prompt = buildCompleteAnalysisPrompt(...);
  const result = await this.llmClient.analyze(prompt);
  return this.processResult(result);
}
3

Test Compression

# Test with sample transcript
bun run dev compress sample-transcript.json --verbose

# Verify output quality
bun run dev load-context --format json | jq .

Adding New Memory Features

1

Extend Memory Schema

// Update memory data structures
interface MemoryEntry {
  text: string;
  project: string;
  timestamp: string;
  type: 'memory' | 'overview' | 'decision';  // Add new types
  metadata?: {
    confidence?: number;  // Add new fields
    tags?: string[];
  };
}
2

Update Storage Logic

// src/core/memory/MemoryManager.ts
async saveMemory(entry: MemoryEntry): Promise<void> {
  // Validate new fields
  // Update storage format
  // Handle backwards compatibility
}
3

Update Context Loading

// src/commands/load-context.ts
// Handle new memory types in filtering and display
const memories = jsonObjects.filter(obj =>
  obj.type === 'memory' || obj.type === 'decision'  // Include new types
);

Code Quality Guidelines

TypeScript Best Practices

// ✅ Good: Explicit types and error handling
export async function processMemory(
  memory: MemoryEntry,
  options: ProcessingOptions
): Promise<ProcessingResult> {
  try {
    const result = await this.processor.process(memory);
    return { success: true, data: result };
  } catch (error) {
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
}

// ❌ Avoid: Implicit any types and unhandled errors
export async function processMemory(memory, options) {
  const result = await this.processor.process(memory);
  return result;
}

Error Handling Patterns

// ✅ User-friendly error messages
try {
  await operation();
} catch (error) {
  const userMessage = createUserFriendlyError(
    'Memory loading',
    error.message,
    'Check your installation and try again'
  );
  console.log(userMessage);
  process.exit(1);
}

// ✅ Graceful degradation
try {
  const memories = await loadMemories();
  return memories;
} catch (error) {
  debugLog('Memory loading failed, continuing without context', error);
  return [];
}

CLI Command Patterns

// ✅ Consistent command structure
export async function myCommand(options: OptionValues = {}): Promise<void> {
  try {
    // Validate inputs
    if (!validateOptions(options)) {
      console.error('Invalid options provided');
      return;
    }

    // Show progress for long operations
    console.log('Processing...');

    // Perform operation
    const result = await performOperation(options);

    // Provide clear feedback
    console.log(createCompletionMessage('Operation', result.count, 'items processed'));

  } catch (error) {
    console.error(createUserFriendlyError('Operation', error.message, 'Try again with --verbose'));
  }
}

Release Process

Testing Before Release

1

Local Testing

# Test all major commands
bun run dev install --force
bun run dev status
bun run dev save "Test memory"
bun run dev load-context
bun run dev uninstall
2

Integration Testing

# Test with real Claude Code session
bun run dev install --force
# Start Claude Code, have conversation, verify memory creation
bun run dev load-context  # Verify memories loaded
3

Build Testing

# Test production build
bun run build
node dist/claude-mem.min.js status
node dist/claude-mem.min.js install --force

Version Management

# Update version in package.json
npm version patch  # or minor, major

# Build and publish
bun run publish:latest

Debugging Techniques

Development Debugging

# Enable debug logging
export CLAUDE_MEM_DEBUG=1

# Run with verbose output
bun run dev command --verbose

# Check detailed logs
bun run dev logs --debug --tail 100

Hook Debugging

# Test hooks in isolation
echo '{"source":"test"}' | ./hooks/session-start.sh

# Check hook output and exit codes
echo $?  # Should be 0 for success

# View hook logs
tail -f ~/.claude-mem/logs/hooks.log

Memory System Debugging

# Inspect memory index
head -10 ~/.claude-mem/index/index.jsonl | jq .

# Check Chroma database
ls -la ~/.claude-mem/chroma/

# Test compression manually
bun run dev debug-filter path/to/transcript.json

Contributing Guidelines

Pull Request Process

1

Before Submitting

  • All tests pass locally
  • Code follows style guidelines
  • Documentation updated if needed
  • Breaking changes are documented
2

PR Description

Include:
  • Clear description of changes
  • Motivation and context
  • Testing performed
  • Screenshots if UI changes
  • Related issue numbers
3

Review Process

  • Automated checks must pass
  • Code review by maintainers
  • Integration testing
  • Documentation review

Issue Reporting

When reporting bugs or requesting features:
  • Bug Reports: Include steps to reproduce, expected vs actual behavior, system info
  • Feature Requests: Describe use case, proposed solution, alternatives considered
  • Documentation Issues: Specify what’s unclear or missing

Getting Help


Ready to contribute? Start by exploring the codebase, setting up your development environment, and looking for issues labeled “good first issue” or “help wanted” in the repository.