Skip to content

Instantly share code, notes, and snippets.

@peerasak-u
Last active March 4, 2026 05:10
Show Gist options
  • Select an option

  • Save peerasak-u/06a240f826f6de2f41fa3fb64b6e5d20 to your computer and use it in GitHub Desktop.

Select an option

Save peerasak-u/06a240f826f6de2f41fa3fb64b6e5d20 to your computer and use it in GitHub Desktop.
OpenMemory Plugin Improvement Spec - Project Identity Configuration System

OpenMemory Plugin Improvement Specification

Project Identity Configuration System (Simplified v2.1)


1. Problem Statement

Current Limitations

The existing OpenMemory plugin uses SHA256 hashing of absolute directory paths to generate project identifiers:

function getProjectId(directory: string): string {
  return sha256(directory);
  // /home/tony/second-brain → "a3f7c2d8..."
  // /Users/tony/Projects/second-brain → "e9b2a1f4..." (different!)
}

Critical Issues:

  • Fragile Identity: Moving, renaming, or cloning a project results in complete memory loss
  • Non-Portable: Same project on different machines generates different identities
  • Non-Human-Readable: Impossible to identify which project a hash represents
  • No Team Sharing: Team members working on the same project cannot share memories
  • Ambiguous Scope: Cannot distinguish between global and project memories at a glance

2. Proposed Solution (Simplified)

2.1 Single Source of Truth

Only one location: .opencode/memory.json (or .jsonc)

project-root/
├── .opencode/
│   └── memory.jsonc          # Single configuration file
├── src/
└── README.md

No fallback priority chains. No git remote detection. No SHA256 hashing.

2.2 ID Naming Convention with Prefixes

To enable immediate scope recognition by both humans and agents:

Scope Prefix Format Example
Global/User glob_ glob_{user_name} glob_tony
Project proj_ proj_{memory_id} proj_tony-second-brain

Benefits:

  • Human-readable: Instantly know if memory is global or project-specific
  • Agent-parseable: No ambiguity, prefix tells scope immediately
  • Prevents collisions: glob_tony and proj_tony are distinct
  • Searchable: Can filter by prefix

2.3 Configuration Schema

interface MemoryConfig {
  // Required: Unique identifier for this project (WITHOUT prefix)
  // Format: [a-z0-9_-]+ (kebab-case recommended)
  // Will be stored as: proj_{memory_id}
  memory_id: string;
  
  // Optional: Display name for UI/logging
  name?: string;
  
  // Optional: Additional metadata
  description?: string;
}

Example Configurations:

// Personal project - stored as: proj_tony-second-brain
{
  "memory_id": "tony-second-brain",
  "name": "Second Brain Knowledge Base"
}

// Team project - stored as: proj_company-product-api
{
  "memory_id": "company-product-api",
  "name": "Product API Service",
  "description": "Backend API for product service"
}

2.4 Global User Configuration (Optional)

For global/user scope, no config file needed. System generates:

  • ID: glob_{username} (e.g., glob_tony)
  • Used for: Cross-project preferences, personal knowledge, learned patterns

3. Implementation Specification

3.1 Identity Resolution

function getProjectId(directory: string): string | null {
  const configPath = path.join(directory, '.opencode/memory.json');
  
  // Check for .json first, then .jsonc
  if (!fs.existsSync(configPath)) {
    const jsoncPath = configPath + 'c';
    if (fs.existsSync(jsoncPath)) {
      const config = readConfig(jsoncPath);
      return `proj_${config.memory_id}`;  // Add prefix
    }
    return null;  // No project scope - use user scope only
  }
  
  const config = readConfig(configPath);
  return `proj_${config.memory_id}`;  // Add prefix
}

function getUserId(): string {
  const username = getSystemUsername();  // From env or config
  return `glob_${username}`;  // Add prefix
}

3.2 Final Storage Format

// Project scope: proj_{memory_id}
"proj_tony-second-brain"
"proj_company-api"
"proj_mini-progress-ios"

// Global scope: glob_{username}
"glob_tony"
"glob_alice"
"glob_bob"

3.3 Behavior

If project config exists:

  • Project scope available with proj_ prefix
  • Memories stored under: glob_{user}:proj_{memory_id}

If config doesn't exist:

  • Only global scope available
  • All memories go to: glob_{user}

4. Enhanced Capabilities

4.1 Immediate Scope Recognition

Both humans and agents can instantly identify scope:

// Memory list
[
  { id: "mem_001", scope: "proj_tony-second-brain", content: "API design" },
  { id: "mem_002", scope: "glob_tony", content: "Prefers TypeScript" },
  { id: "mem_003", scope: "proj_mini-progress", content: "Widget architecture" }
]

// Filter by prefix
const projectMemories = allMemories.filter(m => m.scope.startsWith("proj_"));
const globalMemories = allMemories.filter(m => m.scope.startsWith("glob_"));

4.2 Cross-Project Access

Reference any project by its prefixed ID:

openmemory({
  mode: "search",
  query: "React patterns",
  target_project: "proj_tony-mini-progress"  // Clear that it's a project
});

// Or search globally
openmemory({
  mode: "search", 
  query: "coding preferences",
  scope: "user"  // Uses glob_tony automatically
});

4.3 Team Sharing

Same project ID works across all team members:

// File: .opencode/memory.jsonc (committed to repo)
{
  "memory_id": "company-product-api",
  "name": "Product API"
}

// Tony's access: glob_tony:proj_company-product-api
// Alice's access: glob_alice:proj_company-product-api  
// Same project memories, different user isolation

5. Benefits

Aspect Before (SHA256) After (Prefixed Config)
Portability Machine-specific Project-specific
Readability Cryptic hash Meaningful with prefix
Scope Clarity Hidden/obscured Instant via glob_/proj_
Team Sharing Impossible Native support
Relocation Memory loss Preserved
Simplicity Hidden complexity Explicit + prefixed
Cross-Project Impossible Clear prefixed reference
Parseability Requires metadata Prefix tells all

6. Migration Path

Initialize New Project

cd ~/Projects/new-project
mkdir -p .opencode

# Create config (NO prefix in file - added by system)
cat > .opencode/memory.jsonc << 'EOF'
{
  "memory_id": "new-project",
  "name": "My New Project"
}
EOF

# Stored as: proj_new-project

Clone Existing Project

git clone git@github.com:tonunsa/second-brain.git
cd second-brain
# Config already exists - memories automatically available under proj_tony-second-brain

Query Examples

// List all project memories for current user
openmemory({ mode: "list", scope: "project" });
// Returns memories with scope starting with "proj_"

// List all global memories
openmemory({ mode: "list", scope: "user" });
// Returns memories with scope "glob_tony"

// Access specific project from anywhere
openmemory({ 
  mode: "search", 
  query: "architecture",
  target_project: "proj_tony-mini-progress"  // Clear, unambiguous
});

7. Technical Considerations

ID Format Rules

// Valid formats
"glob_tony"                    // Global user
"glob_tony-dev"               // Global user with suffix
"proj_tony-second-brain"      // Project
"proj_company-product-api-v2" // Project with version

// Invalid formats (reserved)
"user_tony"                   // Missing prefix
"project_tony"                // Wrong prefix
"tony-second-brain"           // Missing prefix

Security

  • Config file contains only public memory_id (no prefix)
  • Prefixed ID constructed at runtime
  • User authentication still required at OpenMemory backend
  • Add to .gitignore if you don't want to share project structure

Uniqueness

  • memory_id in config: unique per project
  • Final prefixed ID: glob_ or proj_ ensures no collisions
  • Recommend reverse-DNS style: proj_com.company.product

Performance

  • Single file read on plugin init
  • Prefix added at runtime (no overhead)
  • Cached for session duration

8. Conclusion

Simple rule with clarity:

What You See What It Means
glob_tony Tony's global/user memories (cross-project)
proj_tony-second-brain Tony's Second Brain project memories
proj_company-api Company API project memories

Configuration:

  • Want project scope? Create .opencode/memory.json with memory_id
  • Don't want project scope? Don't create it (uses glob_{user} only)

No magic. No hidden behavior. No SHA256 hashes. Just explicit configuration with clear prefixes.


Specification Version: 2.1 (Simplified with Prefixes) Target Implementation: OpenMemory Plugin v0.1.0+

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment