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
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.
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_tonyandproj_tonyare distinct - Searchable: Can filter by prefix
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:
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
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
}// 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"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}
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_"));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
});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| 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 |
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-projectgit clone git@github.com:tonunsa/second-brain.git
cd second-brain
# Config already exists - memories automatically available under proj_tony-second-brain// 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
});// 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- Config file contains only public
memory_id(no prefix) - Prefixed ID constructed at runtime
- User authentication still required at OpenMemory backend
- Add to
.gitignoreif you don't want to share project structure
memory_idin config: unique per project- Final prefixed ID:
glob_orproj_ensures no collisions - Recommend reverse-DNS style:
proj_com.company.product
- Single file read on plugin init
- Prefix added at runtime (no overhead)
- Cached for session duration
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.jsonwithmemory_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+