The Problem

Twitter/X bookmarks accumulate faster than they can be organized. The built-in bookmarking feature offers no search, no categorization, and no way to surface older saves. Siftly solves this by turning bookmarks into a searchable, locally-hosted knowledge base with AI-powered organization.

What This Does

Siftly is a self-hosted Next.js application that imports Twitter/X bookmarks (via bookmarklet, console script, or OAuth), then runs a 4-stage AI pipeline: entity extraction, vision analysis on images, semantic tagging, and categorization. The result is a searchable interface with AI-powered search (app/ai-search/page.tsx), an interactive mindmap (components/mindmap/), and export tools (lib/obsidian-exporter.ts, lib/exporter.ts).

The core logic lives in lib/ (AI client abstraction, parsers, vision analyzer) and app/api/ (REST routes for bookmarks, categories, import, search). The CLI tool cli/siftly.ts provides a command-line interface. The stack is TypeScript/React/Next.js with Prisma/SQLite for storage and Docker for containerized deployment.

How It Is Wired

The entry point is main in cli/siftly.ts:273, which reaches 12 functions. The shortest traced path from entry to external effect is main -> cmdSearch which hits the database via prisma.bookmark.findMany. The API routes follow a similar pattern: POST handlers in routes like app/api/categorize/route.ts call getProvider and setState before writing to the database.

The highest fan-in functions are getProvider (called from 10 places), getActiveModel (8 places), and getCliAvailability (7 places) — all in lib/settings.ts and lib/ai-client.ts. Changes to these ripple across the entire app. The app/api/analyze/images/route.ts is the most connected route: it defines 3 functions, calls into 27 others, and performs database reads, cryptographic operations, and model inference.

The module graph shows no circular dependencies, but components/mindmap/mindmap-canvas has high instability (imports 5 modules, nothing imports it), making it a leaf that's easy to change but hard to test in isolation.

How To Use It

Setup:

git clone https://github.com/moses-y/Siftly
cd Siftly
npm install
npx prisma generate
npx prisma migrate dev --name init
npx next dev

Configuration: Copy .env.example to .env.local and set ANTHROPIC_API_KEY if not using Claude Code CLI. The app auto-detects auth: Claude Code CLI session (zero config), API key in Settings, or ANTHROPIC_BASE_URL for a proxy.

Running: npm run dev starts the dev server at http://localhost:3000. Docker users can use docker/docker-compose.yml. The CLI entry point is cli/siftly.ts.

Real-World Use

A researcher with 5,000+ bookmarks on AI tools imports them via the bookmarklet, runs the pipeline, then searches "meme about crypto crash" to find a specific post. The mindmap shows related bookmarks by category, and the Obsidian exporter (lib/obsidian-exporter.ts) pushes notes into their vault. All data stays local except AI API calls.

Code Health & Issues

Static analysis (measured, not opinion) found 27 findings: 4 high, 23 medium.

  • High - Duplicated code blocks — 209 repeated 6-line blocks across 24 files (e.g., app/api/bookmarks/route.ts, cli/siftly.ts). Extract shared helpers.
  • High - Deep nesting — 5 files with max indentation depth 8 (e.g., app/categories/page.tsx). Flatten with early returns.
  • High - Oversized filesapp/import/page.tsx at 1,258 lines, plus app/settings/page.tsx and components/bookmark-card.tsx. Split by responsibility.
  • Medium - Empty catch blocksapp/import/page.tsx, app/layout.tsx silently discard errors.
  • Medium - High branching density — 43 branch points over 135 lines in lib/claude-cli-auth.ts.

SDLC observations from the structure: CI exists but never runs the 4 test files (ratio 0.049 tests-to-source), GitHub Actions aren't pinned to commit SHAs, no dependency vulnerability scan, and the Docker base image (node:22-alpine) isn't pinned by digest.

The Bottom Line

Siftly is a functional, feature-rich bookmark manager with a solid AI pipeline and clean architecture at the module level. The main weaknesses are code duplication, oversized files, and CI that doesn't actually test the code. It's a good fit for technical users who want local control over their bookmarks and are comfortable with AI API costs or already have Claude Code CLI.