Self-hosted Twitter/X bookmark manager with AI-powered categorization, search, and visualization.
# Install dependencies
npm install
# Generate Prisma client + create local SQLite database
npx prisma generate
npx prisma db push
# Start the dev server
npx next devApp runs at http://localhost:3000
For a single command that does all of the above and opens the browser automatically:
./start.shIf the user is signed into Claude Code CLI, Siftly uses their Claude subscription automatically. No API key configuration required.
How it works:
lib/claude-cli-auth.tsreads the OAuth token from the macOS keychain (Claude Code-credentials)- Uses
authToken+anthropic-beta: oauth-2025-04-20header in the Anthropic SDK - Falls back to: DB-saved API key →
ANTHROPIC_API_KEYenv var → local proxy
To verify it's working, hit: GET /api/settings/cli-status
npx next dev # Start dev server (port 3000)
npx tsc --noEmit # Type check
npx prisma studio # Database GUI
npx prisma db push # Apply schema changes to DB
npm run build # Production buildapp/
api/
categorize/ # 4-stage AI pipeline (start/stop/status via SSE)
import/ # Bookmark JSON import + dedup
search/ai/ # FTS5 + Claude semantic search
settings/
cli-status/ # GET — returns Claude CLI auth status
test/ # POST — validates API key or CLI auth
analyze/images/ # Vision analysis progress + trigger
bookmarks/ # CRUD + filtering
categories/ # Category management
mindmap/ # Graph data
stats/ # Dashboard counts
import/ # 3-step import UI
mindmap/ # Interactive force graph
settings/ # API keys, model selection
ai-search/ # Natural language search UI
bookmarks/ # Browse + filter UI
categorize/ # Pipeline monitor
lib/
claude-cli-auth.ts # Claude CLI OAuth session (macOS keychain)
categorizer.ts # AI categorization + default categories
vision-analyzer.ts # Image vision + semantic tagging
fts.ts # SQLite FTS5 full-text search
rawjson-extractor.ts # Entity extraction from tweet JSON
parser.ts # Multi-format bookmark JSON parser
exporter.ts # CSV / JSON / ZIP export
prisma/schema.prisma # SQLite schema (Bookmark, Category, MediaItem, Setting, ImportJob)
- Next.js 16 (App Router, TypeScript)
- Prisma 7 + SQLite (local, zero setup, FTS5 built in)
- Anthropic SDK — vision, tagging, categorization, search
- @xyflow/react — mindmap graph
- Tailwind CSS v4
Only DATABASE_URL is required. Everything else is optional:
DATABASE_URL="file:./prisma/dev.db" # required — set by default in .env
ANTHROPIC_API_KEY=sk-ant-... # optional if Claude CLI is signed in
ANTHROPIC_BASE_URL=http://localhost:8080 # optional — for local proxiesPOST to /api/categorize with {} body. Monitor progress via GET /api/categorize (returns SSE stream).
Edit DEFAULT_CATEGORIES array in lib/categorizer.ts. Add name, slug, hex color, and description. The description text is passed verbatim to Claude — be specific.
Append a domain string to KNOWN_TOOL_DOMAINS in lib/rawjson-extractor.ts.
curl -X POST http://localhost:3000/api/settings/test \
-H "Content-Type: application/json" \
-d '{"provider":"anthropic"}'
# Returns: {"working": true}curl http://localhost:3000/api/settings/cli-status
# Returns: {"available": true, "subscriptionType": "max", "expired": false}SQLite file at prisma/dev.db. Schema models:
Bookmark— tweet text, author, raw JSON, semantic tags, enrichment metadataMediaItem— images/videos/GIFs with AI visual tagsBookmarkCategory— bookmark↔category with confidence score (0–1)Category— name, slug, color, AI descriptionSetting— key/value store (API keys, model choice)ImportJob— import file tracking
After schema changes: npx prisma db push