This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
Overnight is a small agent that reads the things I don't want to read, overnight,
and hands me a two-line brief per item in the morning.
You point it at a folder, a single file, a URL, or stdin. It reads every item,
runs an open-weight model on my own machine, and writes a two-sentence brief
per item to a markdown file. I wake up, open one file, I'm caught up.
The effort it saves is attention, not time. I read a lot of things that are three
paragraphs of setup for two sentences of content β support tickets, changelogs,
incident reports. Reading them is not hard, it's wasteful. And the timing makes it
worse: nobody wants to open forty tabs at 8am. So the fix isn't a better reader,
it's doing the reading while I'm asleep.
That's the laziness it rewards. Not "I don't want to work" β "this task should not
cost me attention."
_2 item(s), local mode, model `qwen2.5-1.5b-instruct-q4_k_m.gguf`_
- **a.txt** β The first sentence is here. The second sentence is beyond it.
- **b.txt** β The server is up. The team is working.
Three commands cover everything:
python3 overnight.py --watch ~/inbox --out ~/morning-brief.md
python3 overnight.py --url https://example.com/feed --out brief.md
cat notes.txt | python3 overnight.py --out brief.md
That's the whole tool. There is no cleverness in it β it's a watcher, a model, and
a file. Which is exactly why it fits "Slow and Steady": it runs every night
without being asked, and it produces the same correct result every time.
Live: https://92.5.41.244:8000/overnight/ β paste any text, click the button,
get a two-sentence brief from a local model. Nothing is sent to a provider.
Video: https://github.com/Reggiebro/overnight/releases/download/v1.0.0/demo.mp4
It runs on a free Oracle Cloud instance (8 vCPU / 24 GB) with the model on disk.
It also proves the thing works on hardware that isn't my laptop β I had to move it
because my old machine has a firmware thermal trip and was shutting itself down
under CPU load. The agent now lives somewhere it can't cook itself.
The summariser is a GGUF model sitting on disk β currently Qwen 2.5 1.5B Q4_K_M.
The harness is about 250 lines of Python with no SDK from any vendor. It talks to
llama-cli as a subprocess, or to llama-server on localhost:8080 when a server
is already running (which keeps the model resident, so a second item costs one
forward pass instead of a full reload).
That open-source core is not decorative β it's what makes the project work. Here's
the concrete reason a closed API would have made most of the above impossible:
--model at any GGUF and the pipeline is
unchanged. Better model comes out? Drop it in. Want to fine-tune on your own
vocabulary? You can, because you own the weights.
The last one mattered most to me. A closed model would be a black box that can
change under me without notice. An open one is a file I can inspect.
Because the reading stays mine. That's the whole argument.
I read things that are awkward to hand to a third party: incident notes with
internal hostnames, draft docs that aren't published, tickets with customer names.
With a closed API I'd be choosing between not using the tool and shipping that
text somewhere I don't control. With an open model on disk, there's no third party
to leak to, no account to suspend, and no provider that can change its terms
under me. The tool works on a plane. It costs nothing when I run it every night.
And if the model gets worse, I swap it β I'm not waiting for someone else's
roadmap.
Open innovation made the project possible. Closed would have made it a trade-off.
The tool is honest about what it did, and that took more care than the summary
logic.
The output header says local mode only when the model actually produced the
brief. If no model is found, it says extractive mode and takes the first and
last sentence β a real compression, not an invention. And if there's genuinely
nothing to summarise, it exits non-zero rather than quietly writing an empty file.
There's a subtler version of the same problem. find_model() searches a few
directories and picks the smallest usable GGUF. If it just returned the first file
it found, a truncated download would be reported as "local mode" while every call
silently fell back to the extractive path β the header would be lying. So it probes
each candidate with a real load before returning it, and rejects anything that
doesn't actually load. The header can be trusted because the check is real.
A failed URL fetch is handled the same way: it becomes an item that literally says
[fetch failed: HTTP 502], so a Cloudflare error page never gets summarised into
fake news in your morning brief.
That's the standard I held it to: the tool never claims more than it did.
I'd rather say this than have you find out:
I'm listing these because the interesting part of the project isn't that it
summarises text β that's easy. The interesting part is that it does so with
nothing leaving the machine, no account, and no bill, and still tells you
truthfully what happened.
git clone https://github.com/Reggiebro/overnight
cd overnight
python3 -m pytest tests/ -q
python3 overnight.py --watch ~/inbox --out ~/morning-brief.md
The tests are worth a look β they cover the claims I made above rather than just
that functions return things. A corrupt GGUF is rejected, a failed fetch becomes
an explicit error, the extractive fallback is deterministic, and the header never
claims local mode without a model. CI runs the same suite on Python 3.10β3.12
and is green.
There's a --json flag if you want to pipe it into something else, and a cron
line in the README if you want it to actually run while you sleep.
I'm entering for Best Use of GitHub Copilot β the workflow automation here is
GitHub Actions: the test suite runs automatically on every push across three
Python versions, plus a no-model smoke test that verifies the tool still produces
a correct extractive brief with no model present. That's the category where this
project's automation actually shows.
I've been running it nightly. The payoff is small and specific: I stopped opening
the inbox folder in the morning. I open one file instead of forty tabs, and the
day starts without the "read forty things before coffee" tax.
The tool has no cleverness in it. It's a watcher, a model, and a file. It works
because it runs every night without being asked and produces the same correct
result. Slow and steady: run it every night, trust it in the morning.