Features
Each capability earns its place by saving you a decision: what's worth reading, what you've already seen, and what you can safely ignore.
Every article gets a 0–10 relevance score, a 1–2 sentence summary, and a category, all from your local Ollama model, ranked against the interests you define.
For any saved story, pull a TL;DR on demand. Cruxwire fetches the full linked article and summarizes the actual body with your local model, not just the feed blurb, so you can triage Read Later without opening tabs.
Articles about the same story across outlets are clustered by embedding similarity and shown as one card, with the rest of the coverage collapsed underneath.
A per-source affinity multiplier and an embedding-based taste boost float up what you open and save, and sink what you dismiss. Learned for you, no manual tuning.
Unread stories are carried across runs and pruned by a rank-weighted lifespan inside a floor/ceiling band, so the inbox never goes dry or floods.
A hero plus a "Latest" grid and an "Earlier this week" rail that stay height-matched. Dismissing a story promotes the next-ranked one, so sections never sit empty.
Filter the Home view to stories about a topic by meaning, not just keyword match, "did you hear about X?", powered by the same local embeddings. A filter, not a chatbot.
Literal title keywords plus a semantic "topics to avoid" filter, on top of a built-in deal/spam regex. Mute the things you never want to see.
Ranking, ingestion, schedule, retention, blocklist, and model choices are all editable in-app and apply on the next run, no restart.
Read / Read Later / History sync through the server. Clear it on your laptop, it's cleared on your phone, and it all works offline from local cache.
When the same story is carried by several outlets, that breadth becomes a ranking signal, a widely covered story is boosted (within bounds), and the extra coverage collapses neatly under one card.
Add, validate, and remove RSS/Atom feeds right in the UI, Cruxwire checks a URL before you add it and tracks each source's opens, saves, and dismisses so you can see what's earning its place.
Semantic search
Type what you're curious about and Cruxwire filters the digest to stories that are semantically close, even when none of your words appear in the headline. It runs entirely on local embeddings, so there's no cloud round-trip and no generated answer to second-guess.
Semantic search, ranked by embedding similarity.
Retention
Cruxwire keeps at least a floor and at most a ceiling of unread stories. Each story's lifespan scales with its rank, so the best stories linger and weak ones age out fast. A hard cap guarantees nothing overstays its welcome.
History ages out after a few days; Read Later is curated by hand and never aged. Your learned source stats persist independently, so cleanup never costs you preferences.
RETAIN_FLOOR = 25 # keep at least this many unread
RETAIN_CEILING = 60 # never carry more than this
RETAIN_BASE_TTL_HOURS = 24 # lifespan of lowest-ranked
RETAIN_MAX_TTL_HOURS = 72 # lifespan of highest-ranked
RETAIN_HARD_MAX_AGE = 120 # absolute cutoff (hours)
Privacy by design
There are no accounts, no analytics, and no third-party calls beyond fetching the feeds you choose and your own Ollama endpoint. Scoring, embeddings, and search all run locally. Runtime data sits unencrypted on your volume, yours to back up and protect.
Cruxwire is built for a single trusted user on a private network. It ships with no authentication by design, so keep it on your LAN or behind a reverse proxy, see the security notes in the setup guide.
Every endpoint is reachable by anyone who can reach the port. Keep Cruxwire on a trusted private network, a homelab LAN, a Tailscale/WireGuard tailnet, or localhost, and never expose port 8090 directly to the internet.
The setup guide covers requirements, the Compose file, Ollama models, and how to keep it safely on your network.