Skip to main content
Glama
bear-data-decoder.tsโ€ข5.22 kB
#!/usr/bin/env node // Bear Data Decoder - Attempt to extract readable data from CloudKit records import sqlite3 from 'sqlite3'; import * as path from 'path'; import * as os from 'os'; const BEAR_CLOUDKIT_DB = path.join( os.homedir(), 'Library/Containers/net.shinyfrog.bear/Data/CloudKit/c92f39c6ea98f57c13f84f9b283e7a7613347d0b/Records/Records.db' ); interface BearRecord { recordID: string; zoneIdentifier: string; modificationTime: number; recordData: Buffer; } // Try to extract text from binary data function extractTextFromBuffer(buffer: Buffer): string[] { const texts: string[] = []; const text = buffer.toString('utf8'); // Look for readable text sequences (at least 4 characters, printable ASCII) const textMatches = text.match(/[\x20-\x7E]{4,}/g); if (textMatches) { texts.push(...textMatches); } // Also try looking for UTF-8 sequences const utf8Matches = text.match(/[^\x00-\x1F\x7F-\x9F]{4,}/g); if (utf8Matches) { texts.push(...utf8Matches.filter(t => !textMatches?.includes(t))); } return texts.filter(t => t.length >= 4); } // Extract potential notes data function analyzeNoteRecord(record: BearRecord): any { const texts = extractTextFromBuffer(record.recordData); // Look for common note patterns const notePatterns = { titles: texts.filter(t => t.length < 100 && !t.includes('\n')), content: texts.filter(t => t.length > 20), tags: texts.filter(t => t.startsWith('#') || (t.includes('tag') && t.length < 50)), markdown: texts.filter(t => t.includes('#') || t.includes('*') || t.includes('`')), }; return { recordID: record.recordID, modificationTime: new Date(record.modificationTime * 1000), extractedTexts: texts.slice(0, 10), // First 10 text sequences patterns: notePatterns, dataSize: record.recordData.length, }; } // Main function to decode Bear data function decodeBearData(): Promise<void> { return new Promise((resolve, reject) => { const db = new sqlite3.Database(BEAR_CLOUDKIT_DB, sqlite3.OPEN_READONLY, (err) => { if (err) { reject(err); return; } console.log("๐Ÿ” Decoding Bear CloudKit data...\n"); // Get all notes records const query = ` SELECT recordID, zoneIdentifier, modificationTime, recordData FROM Record WHERE zoneIdentifier LIKE '%Notes%' AND recordData IS NOT NULL ORDER BY modificationTime DESC `; db.all(query, (err, rows: BearRecord[]) => { if (err) { console.error("Error fetching records:", err); db.close(); reject(err); return; } console.log(`๐Ÿ“Š Found ${rows.length} note records\n`); rows.forEach((record, index) => { console.log(`๐Ÿ“ Record ${index + 1}:`); console.log(` ID: ${record.recordID.substring(0, 50)}...`); const analysis = analyzeNoteRecord(record); console.log(` Modified: ${analysis.modificationTime.toISOString()}`); console.log(` Data size: ${analysis.dataSize} bytes`); if (analysis.extractedTexts.length > 0) { console.log(` ๐Ÿ“„ Extracted text snippets:`); analysis.extractedTexts.slice(0, 5).forEach((text: string, i: number) => { const clean = text.replace(/\s+/g, ' ').substring(0, 80); console.log(` ${i + 1}. ${clean}${text.length > 80 ? '...' : ''}`); }); } if (analysis.patterns.titles.length > 0) { console.log(` ๐Ÿท๏ธ Potential titles: ${analysis.patterns.titles.slice(0, 2).join(', ')}`); } if (analysis.patterns.tags.length > 0) { console.log(` ๐Ÿ”– Potential tags: ${analysis.patterns.tags.slice(0, 3).join(', ')}`); } console.log(''); }); // Try to find tag records console.log("๐Ÿ” Looking for tag data...\n"); const tagQuery = ` SELECT recordID, zoneIdentifier, recordData FROM Record WHERE (recordID LIKE '%tag%' OR recordID LIKE '%Tag%' OR zoneIdentifier LIKE '%tag%') AND recordData IS NOT NULL `; db.all(tagQuery, (err, tagRows: BearRecord[]) => { if (err) { console.error("Error fetching tag records:", err); } else { console.log(`๐Ÿ“Š Found ${tagRows.length} potential tag records\n`); tagRows.forEach((record, index) => { console.log(`๐Ÿ”– Tag Record ${index + 1}:`); console.log(` ID: ${record.recordID}`); const texts = extractTextFromBuffer(record.recordData); if (texts.length > 0) { console.log(` Extracted: ${texts.slice(0, 3).join(', ')}`); } console.log(''); }); } db.close(); resolve(); }); }); }); }); } // Run if called directly if (require.main === module) { decodeBearData().catch(console.error); } export { decodeBearData };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/philgetzen/bear-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server