Self-hosted Twitter/X bookmark manager with AI-powered organization
Import Β· Analyze Β· Categorize Β· Search Β· Explore
Siftly turns your Twitter/X bookmarks into a searchable, categorized, visual knowledge base β running entirely on your machine. No cloud, no subscriptions, no browser extensions required. Everything stays local except the AI API calls you configure.
It runs a 4-stage AI pipeline on your bookmarks:
π₯ Import (built-in bookmarklet or console script β no extensions needed)
β
π·οΈ Entity Extraction β mines hashtags, URLs, mentions, and 100+ known tools from raw tweet data (free, zero API calls)
β
ποΈ Vision Analysis β reads text, objects, and context from every image/GIF/video thumbnail (30β40 visual tags per image)
β
π§ Semantic Tagging β generates 25β35 searchable tags per bookmark for AI-powered search
β
π Categorization β assigns each bookmark to 1β3 categories with confidence scores
After the pipeline runs, you get:
- AI search β find bookmarks by meaning, not just keywords ("funny meme about crypto crashing")
- Interactive mindmap β explore your entire bookmark graph visually
- Filtered browsing β grid or list view, filter by category, media type, and date
- Export tools β download media, export as CSV / JSON / ZIP
- Node.js 18+
- npm (comes with Node.js)
That's it. If you have Claude Code CLI installed and signed in, AI features work automatically β no API key needed.
git clone https://github.com/viperrcrypto/Siftly.git
cd Siftly
./start.shstart.sh installs dependencies, sets up the database, checks for Claude CLI auth, and opens http://localhost:3000 automatically.
If you're using Claude Code to set up the project, it will read CLAUDE.md and know exactly how to get started. Just open the project folder:
git clone https://github.com/viperrcrypto/Siftly.git
claude Siftly/Claude Code will handle setup and start the app using your existing Claude subscription β no extra configuration needed.
git clone https://github.com/viperrcrypto/Siftly.git
cd Siftly
npm install
npx prisma generate
npx prisma migrate dev --name init
npx next devSiftly automatically detects the best available auth method β no configuration needed in the most common case.
| # | Method | How |
|---|---|---|
| 1 | Claude Code CLI (zero config) | Already signed in? Siftly reads your session from the macOS keychain automatically |
| 2 | API key in Settings | Open Settings in the app and paste your key |
| 3 | ANTHROPIC_API_KEY env var |
Set in .env.local or your shell environment |
| 4 | Local proxy | Set ANTHROPIC_BASE_URL to any Anthropic-compatible endpoint |
If you use Claude Code, you're already signed in. Siftly detects your session from the macOS keychain and uses your Claude subscription (Free/Pro/Max) automatically.
The Settings page shows a green "Claude CLI detected β no API key needed" badge with your subscription tier when this is active.
Note: This works on macOS. On Linux/Windows, add an API key in Settings instead.
- Go to console.anthropic.com
- Create a new API key
- Open Siftly β Settings β paste it in
New accounts include $5 free credit β enough for thousands of bookmarks at Haiku pricing (~$0.00025/bookmark).
Siftly has built-in import tools β no browser extensions required. Go to the Import page and choose either method:
- Go to Import in the Siftly sidebar
- Drag the "Export X Bookmarks" link to your browser's bookmark bar (or right-click the bookmark bar β Add Bookmark β paste the URL)
- Go to x.com/i/bookmarks while logged in to X
- Click "Export X Bookmarks" in your bookmark bar β a purple button appears on the page
- Click "βΆ Auto-scroll" β the tool scrolls through and captures all your bookmarks automatically
- When complete, click the purple "Export N bookmarks" button β
bookmarks.jsondownloads - Back in Siftly β Import β drop or upload the file
- Go to x.com/i/bookmarks while logged in to X
- Open DevTools: press
F12(Windows/Linux) orββ₯J(Mac), then go to the Console tab - Copy the console script from the Siftly Import page, paste it into the console, and press Enter
- Click "βΆ Auto-scroll" and wait for all bookmarks to be captured
- Click the export button β
bookmarks.jsondownloads automatically - Back in Siftly β Import β upload the file
Re-import anytime β Siftly automatically skips duplicates and only adds new bookmarks.
Categorization starts automatically as soon as you import. You can also trigger it manually from:
- The Import page (after upload)
- The Mindmap page (when bookmarks are uncategorized)
- The Categorize page in the sidebar
| Stage | What it does |
|---|---|
| Entity Extraction | Mines hashtags, URLs, @mentions, and 100+ known tool/product names from stored tweet JSON β free, zero API calls |
| Vision Analysis | Analyzes every image, GIF, and video thumbnail β OCR text, objects, scene, mood, meme templates, 30β40 visual tags per image |
| Semantic Tagging | Generates 25β35 precise search tags per bookmark by combining tweet text + image context. Also extracts sentiment, people, and company names. |
| Categorization | Assigns 1β3 categories per bookmark with confidence scores using all enriched data |
The pipeline is incremental β if interrupted, it picks up where it left off. Use "Re-run everything (force all)" to re-analyze bookmarks that were already processed.
Natural language queries across all bookmark data:
- "funny meme about crypto crashing"
- "react hooks tutorial"
- "bitcoin price chart"
- "best AI coding tools"
Searches tweet text, image OCR, visual tags, semantic tags, and categories simultaneously using a full-text search index (FTS5) + Claude semantic reranking. Results are ranked by relevance with AI-generated explanations for each match.
Interactive force-directed graph showing all bookmarks organized by category:
- Expand/collapse any category to reveal its bookmarks
- Click a bookmark node to open the original tweet on X
- Color-coded legend by category
- If bookmarks aren't categorized yet, an inline AI Categorize button starts the pipeline without leaving the page
- Grid view (masonry layout) or List view
- Filter by category, media type (photo / video), or search text
- Sort by newest or oldest
- Pagination with 24 items per page
- Active filter chips β removable individually or all at once
- Hover any card to download media or jump to the original tweet
8 default categories pre-seeded with AI-readable descriptions:
| Category | Color |
|---|---|
| Funny Memes | Amber |
| AI Resources | Violet |
| Dev Tools | Cyan |
| Design | Pink |
| Finance & Crypto | Green |
| Productivity | Orange |
| News | Indigo |
| General | Slate |
Create custom categories with a name, color, and optional description. The description is passed directly to the AI during categorization β the more specific, the more accurate the results.
- CSV β spreadsheet-compatible with all fields
- JSON β full structured data export
- ZIP β exports a category's bookmarks + all media files with a
manifest.csv
Press Cmd+K (Mac) or Ctrl+K (Windows/Linux) to search across all bookmarks from anywhere in the app.
All settings are manageable in the Settings page at /settings or via environment variables:
| Setting | Env Var | Description |
|---|---|---|
| Anthropic API Key | ANTHROPIC_API_KEY |
Optional if Claude CLI is signed in β otherwise required for AI features |
| API Base URL | ANTHROPIC_BASE_URL |
Custom endpoint for proxies or local Anthropic-compatible models |
| AI Model | Settings page only | Haiku 4.5 (default, fastest/cheapest), Sonnet 4.6, Opus 4.6 |
| OpenAI Key | Settings page only | Alternative provider if no Anthropic key is set |
| Database | DATABASE_URL |
SQLite file path (default: file:./prisma/dev.db) |
Point Siftly at any Anthropic-compatible server:
ANTHROPIC_BASE_URL=http://localhost:8080siftly/
βββ app/
β βββ api/
β β βββ analyze/images/ # Batch image vision analysis (GET progress, POST run)
β β βββ bookmarks/ # List, filter, paginate, delete
β β β βββ [id]/categories/ # Per-bookmark category management
β β βββ categories/ # Category CRUD
β β β βββ [slug]/ # Individual category operations
β β βββ categorize/ # 4-stage AI pipeline (start, status, stop)
β β βββ export/ # CSV, JSON, ZIP export
β β βββ import/ # JSON file import with dedup + auto-pipeline trigger
β β β βββ bookmarklet/ # Bookmarklet-specific import endpoint
β β β βββ twitter/ # Twitter-specific import endpoint
β β βββ link-preview/ # Server-side OG metadata scraper
β β βββ media/ # Media proxy/download endpoint
β β βββ mindmap/ # Graph nodes + edges for visualization
β β βββ search/ai/ # Natural language semantic search (FTS5 + Claude)
β β βββ settings/ # API key + model config
β β β βββ cli-status/ # Claude CLI auth detection endpoint
β β β βββ test/ # API key validation endpoint
β β βββ stats/ # Dashboard stats
β βββ ai-search/ # AI search page
β βββ bookmarks/ # Browse, filter, paginate
β βββ categories/ # Category management
β β βββ [slug]/ # Category detail page
β βββ categorize/ # Pipeline monitor with live progress
β βββ import/ # 3-step import flow (instructions β upload β categorize)
β βββ mindmap/ # Interactive graph
β βββ settings/ # Configuration
β βββ page.tsx # Dashboard
β
βββ components/
β βββ mindmap/ # Mindmap canvas, nodes, edges
β β βββ mindmap-canvas.tsx
β β βββ category-node.tsx
β β βββ tweet-node.tsx
β β βββ root-node.tsx
β β βββ chain-edge.tsx
β β βββ mindmap-context.ts
β βββ command-palette.tsx # Cmd+K global search
β βββ nav.tsx # Sidebar navigation
β βββ theme-toggle.tsx # Light/dark mode
β
βββ lib/
β βββ categorizer.ts # AI categorization logic + default categories
β βββ claude-cli-auth.ts # Claude CLI OAuth session detection (macOS keychain)
β βββ vision-analyzer.ts # Image analysis + batch semantic tagging
β βββ image-context.ts # Shared image context builder
β βββ fts.ts # SQLite FTS5 full-text search index
β βββ rawjson-extractor.ts # Entity extraction from raw tweet JSON
β βββ parser.ts # Multi-format JSON parser
β βββ exporter.ts # CSV, JSON, ZIP export
β βββ types.ts # Shared TypeScript types
β βββ db.ts # Prisma client singleton
β
βββ prisma/
β βββ schema.prisma # SQLite schema
β
βββ start.sh # One-command launcher (install + DB setup + open browser)
βββ CLAUDE.md # Instructions for Claude Code AI assistant
Bookmark β tweet text, author, date, raw JSON, semantic tags, enrichment metadata
βββ MediaItem β images / videos / GIFs with AI-generated image tags
βββ BookmarkCategory β category assignments with confidence scores (0β1)
Category β name, slug, hex color, AI-readable description
Setting β key-value store (API keys, model preferences)
ImportJob β tracks import file status and progress
Siftly uses Prisma migrations for relational schema changes.
In development, run npx prisma migrate dev --name <change-name> when schema changes.
For runtime/prod-style startup, apply committed migrations with npx prisma migrate deploy.
FTS5 (bookmark_fts) is managed at runtime in lib/fts.ts, not in schema.prisma.
This is intentional for now because Prisma does not model SQLite virtual table definitions directly.
For Prisma command and workflow details, see:
- https://www.prisma.io/docs/orm/prisma-migrate/workflows/development-and-production
- https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/generating-prisma-client
| Technology | Version | Role |
|---|---|---|
| Next.js | 16 | Full-stack framework (App Router) |
| TypeScript | 5 | Type safety throughout |
| Prisma | 7 | ORM + migrations |
| SQLite | β | Local database β zero setup, includes FTS5 |
| Tailwind CSS | v4 | Styling |
| Anthropic SDK | β | Vision, semantic tagging, categorization, search |
| @xyflow/react | 12 | Interactive mindmap graph |
| Framer Motion | 12 | Animations |
| Radix UI | β | Accessible UI primitives |
| JSZip | β | Category ZIP export |
| Lucide React | β | Icons |
# One-command start (installs, sets up DB, opens browser)
./start.sh
# Or manually:
npm install
npx prisma generate
npx prisma migrate dev --name init
npx next dev
# Type check
npx tsc --noEmit
# Open database GUI
npx prisma studio
# Build for production
npm run build && npm startEdit DEFAULT_CATEGORIES in lib/categorizer.ts. Each entry needs:
{
name: 'My Category', // Display name
slug: 'my-category', // URL-safe identifier (must be unique)
color: '#6366f1', // Hex color shown in UI
description: '...', // Natural language description β used verbatim in AI prompts
}The description field directly shapes how the AI classifies bookmarks. Be specific.
Add domain strings to KNOWN_TOOL_DOMAINS in lib/rawjson-extractor.ts to have the entity extractor automatically recognize links to those tools in tweet data.
- All data is stored locally in a SQLite file on your machine
- The only external calls are to the AI provider you configure (tweet text + image data)
- No telemetry, no tracking, no accounts required
- Your bookmarks never touch any third-party server except your configured AI endpoint
If Siftly saves you time, consider leaving a tip β
MIT β see LICENSE
Built by @viperr Β· Self-hosted Β· No extensions Β· No cloud