跳到正文
DEV Community· Snippbot·· 2 小時前AI 評分63

Night Scout 用 Gemma 整理夜間資訊並為專案提出下一步

Night Scout: Gemma gathers stuff of interest so I wake up to a powerful digest and next steps

AI 導讀

Night Scout 是作者開發的開源工具,透過本機 Gemma 整理夜間資訊,按用戶關注主題生成晨間摘要,並為指定專案提出下一步。它讀取 YouTube 頻道、網誌、Hacker News、Reddit、Bluesky、Mastodon 和 GitHub releases,摘要最多收錄 25 則。

正文

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

As with many of you, I browse Hacker News, then Reddit, or Bluesky, then maybe hit up a couple of YouTube videos. Occasionally, a few blogs. An hour later I've read a lot of headlines and a lot of summaries, and I've done nothing. There's a crap ton of exciting AI development, that leaves my head buzzing. There's just too much to wrap my head around and I'm pulled in a ton of directions. There's a bunch of ideas I want to chase and tools I want to try.

I realize we need an AI curator of sources of interest.

I don't want another summarizer. I want the night's few stories that matter waiting with the coffee, and for the things I'm building, a next step.

What I Built

Night Scout is an overnight scout. Before bed I do nothing. Overnight it reads the feeds I'd otherwise doom-scroll (YouTube channels, blogs, Hacker News, Reddit, Bluesky, Mastodon and GitHub releases), and a local Gemma model reads the most promising items.

The Digest needs nothing but topics. I type the topics I follow in my own words ("Local LLMs", "AI coding agents", "Security"). Gemma files each item it reads under one of them with a strict score, and only stories at 80 % or more make the Digest, 25 at most. Each has a plain summary, three to five key points and, for a video, the player right in the card. Weak titles (a list of names, a wall of hashtags, another language) get a short Gemma headline, with the original underneath. Everything else from the night sits one click below, ranked by similarity, so nothing is hidden.

For the night of Oct 22 the Digest opened with "Sixteen stories for your topics. Gemma read 40 of the 90 new items against your 4 topics." Nine were Local LLMs, four AI coding agents, three Security, none Model Context Protocol; the other 74 items were under Everything else. (The Digest is newer than that overnight run, so I filed that night's 40 judged items against the four topics afterwards, with the app's own code on the same Gemma.)

Add your projects and it tells you what to do. Point Night Scout at project folders and a second page, Actions, appears. Each pick is labelled for the project it fits: an Issue to check, a Change to track, an Improvement to adopt, or simply Relevant. It shows which profile entry it matched and comes with a typed next step:

  • Try it: an install and smoke-test plan I can run in a throwaway sandbox with one click, after I read the exact commands and confirm.
  • Research more: Gemma reads the full article or video transcript and writes a short brief for that specific project.
  • Note for project: a markdown note dropped into the project's repo, only when I click.
  • Watch later, or 👍 / 👎 to tune what it lets through next time.

I don't write a keyword list. Night Scout reads each project's README and dependency files, and Gemma turns them into a small, editable profile: what the project is for, its stack, its key dependencies, and the kinds of news that would change what I do next ("new releases of feedparser", "security advisories for pydantic"). Whatever I write there is exactly what Gemma judges against. Under the picks, Gemma suggests two small new project ideas inspired by the night's reading.

Here's a real night, Oct 21, with a demo profile of three public projects (Night Scout itself, Simon Willison's llm CLI and the MCP TypeScript SDK): 12 feeds, 140 new items, 40 pre-filtered for Gemma, all 40 judged in about 14 minutes on a 16 GB M4 Mac with 0 failures, and 7 picks in the morning:

  • Issue: a compromised LiteLLM release on PyPI that installs a credential stealer. Next step: check whether LiteLLM is a transitive dependency and pin a known safe version.
  • Change: llm-tools-datasette 0.1.1, which fixes breakage from an httpx2 migration.
  • Improvement: llm-echo 0.5, a debug model for testing tool calls.
  • Relevant: a new Ollama release, an MCP memory server matched to the TypeScript SDK, and two more.

(I added the labels a day later, by running the new judge over that night's seven picks.) The next night, Oct 22, was quieter: 90 new items, all 40 candidates judged in 11.6 minutes, 2 picks (an Ollama release as a Change, the OpenAI CLI as Relevant) and two project ideas. That's the point. Some mornings there's little worth doing, and Night Scout says so instead of filling a feed.

Scout key terms. A feed only shows what's new. When I follow a source I can add a few terms, and Night Scout looks for them once across the whole source, at any age. Every night after that, new posts that mention one go to the front of Gemma's queue. I tried it on Oct 22 with the Higgsfield AI YouTube channel and the terms "kling, veo". YouTube's own channel search returned 9 videos for "kling" and 10 for "veo", but its search is loose, so Night Scout keeps only real whole-word mentions in the title or description: 7 and 4. Ten videos were queued for the first night; the search took between 11 and 43 seconds across my runs, depending on YouTube. Whole-channel search uses the YouTube Data API if I add a key, or yt-dlp without one. That's the one place Night Scout reads public web pages instead of a feed, and only when I ask for it. Each source also has a look back (1 to 14 days, default 3) for its first night.

Ask. An Ask button opens a chat with Gemma on any page. It looks things up before it answers: the Guide, my setup and past runs, every night's items, and web tools (read a page, YouTube transcripts, Hacker News, and web search if I turn it on). Each lookup shows in the drawer as it happens. I can paste a screenshot, or attach text files and PDFs. If I ask it to follow a channel or add a topic, it shows a button under its answer, and nothing changes until I click. A source is checked first, so a card only appears for one that resolves. When Gemma guesses a GitHub owner that doesn't exist and only one repo has that name, the button offers that repo instead, marked "corrected from" the guess.

Listen. With an optional add-on (pip install "night-scout[voice]"), a Listen button reads the Digest aloud: each headline, where it's from, and Gemma's summary, topic by topic. The voice is Kokoro, an open-weight speech model that runs on my Mac, with 28 English voices to pick from (Heart by default). After the nightly run it records the Digest, so it plays at once in the morning. The add-on is optional because it's big: about 1.1 GB for PyTorch plus a 330 MB voice model.

Local by default, cloud optional per job. Out of the box everything runs on Ollama on my machine. Settings → AI Providers shows each job (Judge, Chat, Fallback, Embeddings) and which model does it. I can give a job to Anthropic, Google Gemini, OpenAI, OpenRouter, DeepSeek, Groq, Mistral or xAI instead, and the app marks that job "Leaves this machine". Embeddings always stay local. Keys go into the OS keychain, never into config files.

Demo

Two minutes, built around the questions I kept asking myself, each answered by the app's real screens:

  • 0:00 How many channels, blogs and feeds do I follow, and how many did I actually get to?
  • 0:29 The Digest: what mattered last night, with summaries, key points and the video right in its card.
  • 0:40 Scout key terms: it searches a whole channel for my terms, keeps only the videos that really mention them, and reads the transcripts so I don't have to.
  • 0:52 Upgrade your projects: each action names the project it improves, and why.
  • 1:02 Try it safely: I read the commands, confirm, and a plugin installs and passes its smoke test inside a sandbox that can't see my home folder.
  • 1:14 Build something new: project ideas from what I read and what I already build; one click starts one, README and all.
  • 1:24 Ask: I paste a screenshot and Gemma reads it; ask it to follow a channel and it hands me a button.
  • 1:34 Listen: Kokoro, running locally, reads the Digest aloud.
  • 1:44 Local by default: every job on Gemma on this Mac, and where a cloud model could take one.

The narration is an AI voice (Hume's "Male English Actor") over AI-generated music. The opening and closing stills are AI-generated, and the source chips in the opening are illustrations; everything else is screen capture of the app.

The Night Scout Digest

Code

GitHub logo saixiong / nightscout

Night Scout - find and research topics of your interest into one feed where actionable tasks are created for you to execute

Night Scout

An overnight scout that turns the internet into a short morning Digest, and into next steps for your own projects.

Before bed you do nothing. Overnight, Night Scout reads the feeds you'd otherwise doom-scroll: YouTube channels, blogs, Hacker News, Reddit, Bluesky, Mastodon and GitHub releases. A local Gemma model, running through Ollama, files what matters under the topics you follow, and, if you point it at the projects on your disk, judges what matters to those projects. In the morning you get two pages:

  • Digest (opens first): the night's best stories for your topics, 25 at most, each with a plain summary, the key points and the video right in the card. Everything else from the night is one click below, ranked by similarity, so nothing is hidden. No projects needed.
  • Actions (with projects): a short list of things worth doing, each labelled Issue Change, Improvement…

MIT licensed. Clone it and double-click Night Scout.command (macOS) or Night Scout.cmd (Windows): the first launch installs it and opens a walkthrough in the browser (model, Just the Digest or Digest + My projects, where 📁 Choose folder… picks project folders in Finder or File Explorer, then topics, sources and schedule). From a terminal it's pip install -e . and night-scout setup. After that the scout goes out every night on its own (launchd on macOS, systemd or cron on Linux; on Windows, night-scout schedule prints the one schtasks line to add), and ▶ Run now on the Digest or Actions page sends it out straight away. The README has the two-minute quick start.

How I Built It

The open pieces do all the thinking:

  • Gemma 4 12B (gemma4:12b via Ollama) judges every item, files it for the Digest, proposes actions and answers in Ask. A 4B variant is the configured fallback.
  • EmbeddingGemma 2 (embeddinggemma-2:270m) does the cheap pre-filter and finds near-duplicate stories across sources.
  • Python, FastAPI, feedparser, httpx and pydantic hold it together. The UI is plain vanilla JS on a local JSON API: no frontend build, a strict Content Security Policy, and it works at phone width too.
  • Models are swappable, local first. Ollama is the default; LM Studio or any OpenAI-compatible server works too. Anthropic has its own client; the other cloud providers go through OpenAI-compatible endpoints.

One night is seven steps:

fetch → dedupe → pre-filter → Gemma judges → Gemma proposes → digest → ideas
  1. Fetch from official feeds and public APIs only, politely spaced, with a descriptive User-Agent. Each source fails on its own with a status line ("Reddit r/x: HTTP 429, skipped"), and the run goes on.
  2. Dedupe by canonical URL (tracking parameters stripped, YouTube URL forms folded) and by embedding similarity. A story on both HN and Reddit becomes one item with a little extra "buzz".
  3. Pre-filter: each interest becomes a retrieval query for EmbeddingGemma, so Gemma reads the 40 most likely items instead of 140. Key-term matches go first.
  4. Judge: Gemma returns structured JSON for every item: its topic and score for the Digest, a summary and key points, and with projects a relevance score per project, a label, the matched profile entries and a next step. Matched entries are checked against the profile word for word, so the model can't invent an interest I don't have.
    • Ollama constrains the output to a JSON schema, and pydantic validates it.
    • An invalid answer gets one retry with the exact validation error. If it fails again, it's logged and skipped, never fatal.
  5. Propose typed actions for items above the bar.
  6. Digest as markdown plus the web UI.
  7. Ideas: one more Gemma call turns the night's reading into two side-project ideas.

Three things I learned the honest way:

  • The pre-filter is the product. On the first real run, 13 of Gemma's 40 slots went to items it then scored 0.0: PHP CVEs and game news. Meanwhile two releases that mattered to my demo projects were filtered out. Raw embedding cosines all sat between 0.35 and 0.45, so popularity decided everything. The fix:
    • use EmbeddingGemma's task prompts (task: search result | query: …);
    • turn every profile interest into its own query;
    • normalize similarity across the night's batch.

The next run had 7 on-topic picks instead of 2, and the missing releases came back.

  • Schemas are a conversation, not a cage. Once, Gemma wrote a Python smoke test as separate shell steps (from rank_bm25 import … as a command). Now the Try-it schema rejects source code as a step, and that rejection becomes the feedback on the one retry. The model fixes it itself.
  • Read your tool's build. Homebrew's ollama formula currently ships without the grammar library, so every structured request returned 501 structured output is unavailable. The official build (the ollama-app cask) has it. Night Scout now detects the 501 and falls back to schema-in-prompt plus validation, so it works on both.

The part I spent the most time on is safety. A tool that reads untrusted text from the internet and asks a model to suggest shell commands needs to be boring about it:

  • Nothing runs automatically. The nightly run only proposes, and Ask only offers buttons.
  • A denylist runs at proposal time and again before running. It covers sudo, curl | sh and download-then-run, global installs, credential paths, local services and backgrounded processes. A refused plan shows its reasons instead of a Run button.
  • Confirm page. You see the exact commands, where they'll run, the time limit and a supply-chain warning, then you tick a box.
  • The sandbox is a throwaway container if Docker is around. Otherwise it's a throwaway virtualenv with a scrubbed environment, fenced by the OS: sandbox-exec on macOS blocks my home folder, other drives, local services (including Ollama and the Night Scout UI), the clipboard and launching apps; bubblewrap does the job on Linux. I checked it live: pip install llm-echo plus an import check passed in 10.5 seconds, while reading ~, reaching 127.0.0.1:11434 or reading a keychain item from inside it all fail.
  • Feed text is treated as data. Every prompt says so, including the chat's tool results. Research more and Ask's page reader only fetch public addresses, connecting to the exact IP they checked. The only remote images are YouTube thumbnails (and the youtube-nocookie player, when I press play), allowed by name in a strict Content Security Policy. The UI needs a per-launch key, so other processes on the machine can't click buttons for me.

Testing. Independent review passes audited the code against the spec after each milestone. The first found 3 high and 8 medium issues, including a Linux sandbox with no isolation; the second found 9 more. All are fixed with regression tests. The final build has 556 unit tests and seven Playwright end-to-end kits that drive the real app in a browser: setup, Digest, the guided tour, Digest plus chat, the assistant on real Gemma, sources and providers, 114 of 114 steps passing. Each kit runs sandboxed, with a throwaway home, a throwaway keychain entry and a faked scheduler. The kits earned their keep. They caught chat history dropping tool calls, so Gemma claimed buttons it never made; the drawer hiding proposal cards after a failed tool call; and YouTube feed outages blocking channel adds. All fixed before the final run.

Why Does Open Innovation Matter?

For this project, a closed API would have been a worse product, not just a cheaper one.

  • My project context never leaves the laptop. The profile is a map of what I'm building, including private repos. By default Night Scout reads public feeds in and sends nothing out: the model is on localhost. Cloud models are there if I want one for a job, and the app says plainly which jobs that sends off the machine.
  • $0 per night, forever. Forty judgements plus proposals and embeddings every night is a real token bill on a paid API. Here it's under 15 minutes of a laptop GPU while I sleep. A tool like this only works if it runs every single night without me thinking about cost.
  • It's mine to tune. I swapped embedding models, changed prompts and schemas, picked a smaller fallback for slower machines, and none of that needed anyone's permission or a pricing page.
  • Open weights plus open source means you can check the safety story yourself. Every line that decides what gets proposed, refused or run is in the repo.

And it was simply better at one thing: the judge reads untrusted internet text all night. Running it locally means that text can't trick the model into sending my profile anywhere, because nothing in the loop can send it anywhere.

The Lazy Payoff

  • Before: about 40 minutes a morning across seven sites, and most days nothing came of it.
  • After: the night's reading is done while I sleep. On Oct 22 that was 90 new items, 40 read by Gemma, sixteen stories in the Digest and two picks for my projects. Some mornings it just says "Nothing cleared the bar", and that's the point.

Prior art, for credit and contrast: AI News Brief, Auto-News and news-agent all aggregate, summarize and rank, and they're good at it. Night Scout's bet is different: it files the night under your own topics, it knows your projects, and every pick ends in something you can do.

Prize Categories

  • Best Use of Gemma: Gemma 4 12B files the Digest, judges and plans the Actions with schema-constrained output, and answers in Ask with tools and screenshots; EmbeddingGemma 2 is the pre-filter and dedupe. By default all of it runs locally through Ollama.

來源:DEV Community · dev.to