UNPKG

claude-sesh

Version:

Session explorer for Claude Code - find, search, and resume all your past sessions

147 lines 4.97 kB
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'; import { homedir } from 'os'; import { join } from 'path'; class BookmarksService { dataDir; filePath; data; constructor() { this.dataDir = join(homedir(), '.claude-sesh'); this.filePath = join(this.dataDir, 'bookmarks.json'); this.data = this.loadData(); } loadData() { if (!existsSync(this.dataDir)) { mkdirSync(this.dataDir, { recursive: true }); } if (!existsSync(this.filePath)) { return { version: 1, bookmarks: {} }; } try { const content = readFileSync(this.filePath, 'utf-8'); const parsed = JSON.parse(content); // Convert date strings back to Date objects for (const bookmark of Object.values(parsed.bookmarks)) { bookmark.createdAt = new Date(bookmark.createdAt); bookmark.updatedAt = new Date(bookmark.updatedAt); } return parsed; } catch (error) { console.error('Failed to load bookmarks:', error); return { version: 1, bookmarks: {} }; } } saveData() { try { writeFileSync(this.filePath, JSON.stringify(this.data, null, 2)); } catch (error) { console.error('Failed to save bookmarks:', error); } } getOrCreateBookmark(sessionId) { if (!this.data.bookmarks[sessionId]) { this.data.bookmarks[sessionId] = { sessionId, starred: false, tags: [], note: '', createdAt: new Date(), updatedAt: new Date(), }; } return this.data.bookmarks[sessionId]; } getBookmark(sessionId) { return this.data.bookmarks[sessionId] || null; } getAllBookmarks() { return Object.values(this.data.bookmarks); } getStarredSessions() { return Object.values(this.data.bookmarks).filter(b => b.starred); } toggleStar(sessionId) { const bookmark = this.getOrCreateBookmark(sessionId); bookmark.starred = !bookmark.starred; bookmark.updatedAt = new Date(); this.saveData(); return bookmark.starred; } setStar(sessionId, starred) { const bookmark = this.getOrCreateBookmark(sessionId); bookmark.starred = starred; bookmark.updatedAt = new Date(); this.saveData(); } addTag(sessionId, tag) { const bookmark = this.getOrCreateBookmark(sessionId); const normalizedTag = tag.trim().toLowerCase(); if (normalizedTag && !bookmark.tags.includes(normalizedTag)) { bookmark.tags.push(normalizedTag); bookmark.updatedAt = new Date(); this.saveData(); } return bookmark.tags; } removeTag(sessionId, tag) { const bookmark = this.getOrCreateBookmark(sessionId); const normalizedTag = tag.trim().toLowerCase(); bookmark.tags = bookmark.tags.filter(t => t !== normalizedTag); bookmark.updatedAt = new Date(); this.saveData(); return bookmark.tags; } setTags(sessionId, tags) { const bookmark = this.getOrCreateBookmark(sessionId); bookmark.tags = tags.map(t => t.trim().toLowerCase()).filter(t => t); bookmark.updatedAt = new Date(); this.saveData(); return bookmark.tags; } setNote(sessionId, note) { const bookmark = this.getOrCreateBookmark(sessionId); bookmark.note = note.trim(); bookmark.updatedAt = new Date(); this.saveData(); } getNote(sessionId) { return this.data.bookmarks[sessionId]?.note || ''; } getAllTags() { const allTags = new Set(); for (const bookmark of Object.values(this.data.bookmarks)) { for (const tag of bookmark.tags) { allTags.add(tag); } } return Array.from(allTags).sort(); } getSessionsByTag(tag) { const normalizedTag = tag.trim().toLowerCase(); return Object.values(this.data.bookmarks) .filter(b => b.tags.includes(normalizedTag)) .map(b => b.sessionId); } deleteBookmark(sessionId) { delete this.data.bookmarks[sessionId]; this.saveData(); } // Clean up bookmarks for sessions that no longer exist cleanup(existingSessionIds) { let removed = 0; for (const sessionId of Object.keys(this.data.bookmarks)) { if (!existingSessionIds.has(sessionId)) { delete this.data.bookmarks[sessionId]; removed++; } } if (removed > 0) { this.saveData(); } return removed; } } export const bookmarksService = new BookmarksService(); //# sourceMappingURL=bookmarks.js.map