API Reference
LoreHub provides programmatic access through its MCP (Model Context Protocol) server and command-line interface.
MCP Server
The Model Context Protocol server allows AI assistants and other tools to interact with LoreHub.
Starting the Server
lh serve-mcpThis starts a Model Context Protocol server that AI assistants like Claude can connect to.
Available MCP Tools
The MCP server exposes the following tools:
1. search_lores
Search for lores with wildcards and filters.
{
query: string; // Search query (supports wildcards * and ?)
realm_path?: string; // Realm to search in
type?: string; // Filter by type
province?: string; // Filter by province
limit?: number; // Max results (default: 50)
}2. list_lores
List lores with optional filters.
{
realm_path?: string; // Realm to list from
type?: string; // Filter by type
province?: string; // Filter by province
limit?: number; // Max results (default: 20)
}3. get_lore
Get a specific lore by ID.
{
lore_id: string; // The lore ID
}4. list_realms
List all tracked realms.
No parameters required.
5. create_lore
Create a new lore.
{
realm_path: string; // Where to create the lore
content: string; // The lore content
type: string; // Type of lore
confidence?: number; // 0-100 (default: 80)
why?: string; // Additional context
provinces?: string[]; // For monorepos
sigils?: string[]; // Tags
}6. update_lore
Update an existing lore.
{
lore_id: string;
content?: string;
type?: string;
confidence?: number;
status?: string;
why?: string;
}7. delete_lore
Permanently delete a lore.
{
lore_id: string;
confirm: boolean; // Must be true
}8. archive_lore
Soft delete a lore.
{
lore_id: string;
}9. restore_lore
Restore an archived lore.
{
lore_id: string;
}10. create_relation
Create relationship between lores.
{
from_lore_id: string;
to_lore_id: string;
type: string; // supersedes/contradicts/supports/depends_on/relates_to
}11. delete_relation
Remove relationship between lores.
{
from_lore_id: string;
to_lore_id: string;
type: string;
}12. list_relations
List lore relationships.
{
lore_id: string;
direction?: string; // from/to/both (default: both)
}13. get_realm_stats
Get realm statistics.
{
realm_path: string;
}14. semantic_search_lores
Semantic similarity search.
{
query: string;
realm_path?: string;
threshold?: number; // 0-1 (default: 0.7)
limit?: number; // (default: 20)
}15. find_similar_lores
Find similar lores.
{
lore_id: string;
threshold?: number; // 0-1 (default: 0.5)
limit?: number; // (default: 10)
}MCP Integration Example
Claude Desktop
{
"mcpServers": {
"lorehub": {
"command": "node",
"args": ["/path/to/node_modules/lorehub/dist/mcp/index.js"]
}
}
}CLI JSON Output
Most LoreHub commands support JSON output for scripting.
Search JSON Format
lh search "caching" --format jsonOutput structure:
{
"lores": [
{
"id": "abc123",
"content": "Use Redis for session caching",
"type": "decree",
"confidence": 85,
"sigils": ["redis", "cache", "performance"],
"realm": "main-api",
"created_at": "2024-01-15T10:30:00Z"
}
]
}List JSON Format
lh list --format jsonOutput structure:
{
"lores": [
{
"id": "def456",
"content": "Database migrations timeout on large tables",
"type": "risk",
"confidence": 90,
"provinces": ["database"],
"status": "living"
}
]
}Export Format
lh export --format jsonOutput structure:
{
"version": "1.0",
"exported_at": "2024-01-15T10:30:00Z",
"lores": [
{
"id": "abc123",
"content": "Always use prepared statements",
"type": "wisdom",
"confidence": 100,
"why": "Prevents SQL injection",
"sigils": ["security", "database"],
"status": "living",
"created_at": "2024-01-10T08:00:00Z",
"updated_at": "2024-01-10T08:00:00Z"
}
]
}Data Types
Lore Types
type LoreType =
| "decree" // Architectural or technical choice
| "wisdom" // Something discovered or learned
| "belief" // Unverified belief or hypothesis
| "constraint" // Limitation or restriction
| "requirement" // Business or technical requirement
| "risk" // Potential problem or concern
| "quest" // Future action needed
| "saga" // Major initiative
| "story" // User story
| "anomaly" // Bug or issue
| "other" // MiscellaneousLore Status
type LoreStatus =
| "living" // Active and current (default)
| "ancient" // Outdated but historically important
| "whispered" // Uncertain or unverified
| "proclaimed" // Officially documented
| "archived" // Soft deletedRelation Types
type RelationType =
| "supersedes" // Replaces older knowledge
| "contradicts" // Conflicts with another lore
| "supports" // Reinforces another lore
| "depends_on" // Requires another lore
| "relates_to" // General connectionDatabase Schema
Direct database access is not recommended. Use the CLI or MCP server instead.
Main Tables
-- Realms (tracked repositories)
CREATE TABLE realms (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
path TEXT NOT NULL UNIQUE,
gitRemote TEXT,
isMonorepo BOOLEAN DEFAULT 0,
provinces TEXT, -- JSON array
lastSeen DATETIME,
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Lores (knowledge entries)
CREATE TABLE lores (
id TEXT PRIMARY KEY,
realmId TEXT NOT NULL,
content TEXT NOT NULL,
why TEXT,
type TEXT DEFAULT 'other',
provinces TEXT, -- JSON array
sigils TEXT, -- JSON array
confidence INTEGER DEFAULT 80,
origin TEXT, -- JSON object
status TEXT DEFAULT 'living',
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
updatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (realmId) REFERENCES realms(id)
);
-- Relations between lores
CREATE TABLE lore_relations (
id TEXT PRIMARY KEY,
fromLoreId TEXT NOT NULL,
toLoreId TEXT NOT NULL,
type TEXT NOT NULL,
metadata TEXT, -- JSON object
strength REAL DEFAULT 1.0,
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (fromLoreId) REFERENCES lores(id),
FOREIGN KEY (toLoreId) REFERENCES lores(id),
UNIQUE(fromLoreId, toLoreId, type)
);
-- Embeddings for semantic search
CREATE VIRTUAL TABLE lores_vec USING vec0(
lore_id TEXT PRIMARY KEY,
embedding FLOAT[384]
);
-- Change log for sync
CREATE TABLE change_log (
id TEXT PRIMARY KEY,
entityType TEXT NOT NULL,
entityId TEXT NOT NULL,
realmId TEXT,
operation TEXT NOT NULL,
changes TEXT, -- JSON object
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
syncStatus TEXT DEFAULT 'pending'
);Scripting Examples
Bash
#!/bin/bash
# backup-lores.sh
# Create timestamped backup
BACKUP_FILE="lores-backup-$(date +%Y%m%d-%H%M%S).json"
lh export --format json --output "$BACKUP_FILE"
echo "Backup created: $BACKUP_FILE"Node.js
const { exec } = require('child_process');
const util = require('util');
const execPromise = util.promisify(exec);
async function analyzeLores() {
// Get all lores
const { stdout } = await execPromise('lh export --format json');
const data = JSON.parse(stdout);
// Analyze confidence distribution
const byConfidence = {};
data.lores.forEach(lore => {
const bucket = Math.floor(lore.confidence / 10) * 10;
byConfidence[bucket] = (byConfidence[bucket] || 0) + 1;
});
console.log('Confidence Distribution:');
Object.entries(byConfidence)
.sort(([a], [b]) => a - b)
.forEach(([bucket, count]) => {
console.log(`${bucket}-${parseInt(bucket)+9}: ${count} lores`);
});
}
analyzeLores().catch(console.error);Python
import subprocess
import json
from collections import Counter
def get_lore_stats():
# Execute LoreHub command
result = subprocess.run(
['lh', 'export', '--format', 'json'],
capture_output=True,
text=True
)
data = json.loads(result.stdout)
# Count by type
type_counts = Counter(lore['type'] for lore in data['lores'])
print("Lores by Type:")
for lore_type, count in type_counts.most_common():
print(f" {lore_type}: {count}")
# Average confidence by type
print("\nAverage Confidence by Type:")
for lore_type in type_counts:
lores_of_type = [l for l in data['lores'] if l['type'] == lore_type]
avg_confidence = sum(l['confidence'] for l in lores_of_type) / len(lores_of_type)
print(f" {lore_type}: {avg_confidence:.1f}%")
if __name__ == "__main__":
get_lore_stats()Error Handling
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Command not found |
| 3 | Invalid arguments |
Common Errors
-
Database locked
- Only one LoreHub process can access the database at a time
- Solution: Ensure no other LoreHub commands are running
-
Embeddings not found
- Semantic search requires embeddings to be generated
- Solution: Run
lh migrate-embeddings
-
Realm not found
- The specified path is not a tracked realm
- Solution: Check path or use
lh realm list
Performance Tips
Bulk Operations
For better performance with multiple operations:
# Instead of multiple individual adds
lh add "Decision 1"
lh add "Decision 2"
lh add "Decision 3"
# Create a JSON file and import
cat > bulk-lores.json << EOF
{
"lores": [
{"content": "Decision 1", "type": "decree"},
{"content": "Decision 2", "type": "decree"},
{"content": "Decision 3", "type": "decree"}
]
}
EOF
lh import bulk-lores.jsonSearch Performance
- Use
--limitto reduce result set size - Literal search is faster than semantic search
- Filter by type or province to narrow results
- Hybrid search balances speed and relevance
Best Practices
- Use appropriate types: Choose the most specific lore type
- Set meaningful confidence: Reflect your certainty accurately
- Add context with why: Future you will thank you
- Use consistent sigils: Establish team conventions
- Export regularly: Backup your knowledge base
Support
- GitHub Issues: github.com/RoeeJ/lorehub/issues 
- Documentation: lorehub.dev 
- NPM Package: npmjs.com/package/lorehub