This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady.
This week's theme could have been written for this tool. Slow: the work happens while you're away, one chore at a time, and nobody watches. Steady: every ticket carries an acceptance command and a hard budget cap, so the same chore comes out the same whether you look or not.
Over the past couple of months I built myself a coding agent — deepseeker-code, an open-source CLI + VSCode extension powered by open-weight DeepSeek models. It writes code, runs tools, passes tests. Naturally, I mostly used it to build more software.
Then I noticed the laziest possible use of a coding agent had been staring at me the whole time: every repo I own carries a pile of chores I never do. Fix this TODO. Write the LICENSE. Add a test. None of them is worth a context switch. All of them together are why my repos feel untidy.
So I built lunchshift — a small CLI whose entire purpose is to let a repo work its own shift while I eat.
What it does
Three commands:
lunchshift scan # free, deterministic: find chores, write agent tickets
lunchshift run --window 12:00-14:00 # hand them to the agent, go eat
lunchshift report # what got done, and what it cost
scan is deliberately dumb: it globs source files for TODO: / FIXME: / HACK: markers and checks three hygiene basics — README, LICENSE, test script. No API calls, no cost, no opinions. Each finding becomes a ticket, which is just markdown with frontmatter:
---
title: "Resolve FIXME in src/report.js (line 23)"
accept: npm test
budget-yuan: 0.3
timeout-min: 15
---
Two fields carry the whole design. accept is the shell command that proves the work actually happened — the agent's own claim is never the acceptance criterion. budget-yuan is a hard spend cap: when a ticket burns past its budget, the run stops and says so.
run hands the tickets to the deepseeker-code agent, which works through them serially in isolated git worktrees. Nothing touches your branch until a human looks at it.
Today's actual shift
Here is the unedited summary of the shift I ran earlier today, on the lunchshift repo itself:
Three tickets: one TODO found by scan (it turned into a real CLI feature), one planted trap, one hand-written feature request. 5.8 minutes, completely unattended. When I came back:
The lazy payoff, with receipts
Every ticket settles with a receipt — rounds, cost, cache hit rate, wall time. Today's:
| ticket | rounds | cost | cache hit | time |
|---|---|---|---|---|
--budget-yuan / --timeout-min CLI flags |
22 | ¥0.118 | 97% | 1.7 min |
| fixture TODO (a trap — see below) | 30 | ¥0.166 | 89% | 3.9 min |
pass/fail verdicts in report
|
34 | ¥0.277 | 97% | 4.6 min |
That second shift cost ¥0.56, about eight US cents, most of it inside DeepSeek's off-peak discount window. Across two shifts today: five chores resolved, ¥0.80 total — roughly eleven cents, with a hard cap of ¥0.3 per ticket that the priciest ticket finished under at 92%.
The economics are the point. Unattended agent work only makes sense if a "shift" costs less than the coffee you drink during it — and open-weight models are what get it there.
The ticket that lied
One of today's TODOs was a trap. The file test/fixtures/mini/sample.js contains // TODO: nothing to see here — planted test data. If an agent "resolves" it by deleting the marker, the scanner's own test suite fails, and acceptance rejects the ticket.
The agent read the test, read the scanner's regex, worked out that the marker must survive, and instead replaced the misleading comment with a self-documenting one — keeping the TODO: prefix the test asserts on. One line changed, tests green. The ticket lied; the acceptance command didn't.
The claim it walked back
The best part of today's run: in the first shift, the agent had left a note in report.js explaining that per-ticket pass/fail verdicts could not be surfaced, because done reports carry no machine-readable verdict field. That was wrong — the batch runner writes status: into every report's frontmatter. So shift two got a hand-written ticket with that hint attached. It shipped the feature — plus 86 lines of tests — for ¥0.277, inside its budget.
An agent that doubts something at 9 AM can be handed its own doubt as a ticket and retire it by lunch. That feedback loop is the whole product.
Why open-source AI is load-bearing here
- Open-weight models make the economics work. Unattended micro-shifts only make sense at DeepSeek's price point; with pricier APIs the budget caps would dominate every run.
- The harness is inspectable. Every safety gate — acceptance commands, budget truncation, worktree isolation, "nothing lands on your branch" — is code you can read in the deepseeker-code repo, not a promise in a privacy policy.
- Local-first by design. lunchshift is a single-person local tool. Your code sits in a worktree on your disk; the only thing that leaves your machine is what any LLM call has to send.
Honest limits
- The scanner only finds chores that are literally visible: comment markers and three hygiene checks. It will not invent work — which also means it will not find your architecture problems.
- The agent is good but not infallible. That is exactly why every ticket carries an acceptance command and a budget, and why worktree changes come back as proposals, not commits. (They genuinely arrive uncommitted — reviewing and merging them is the human's half of the shift. This post's demo changes were kept exactly that way.)
- v0.1 targets npm-flavored JavaScript/TypeScript repos, and the scanner speaks Windows and Unix paths unequally well. Early days.
Try it
- lunchshift: github.com/xknk/lunchshift
-
the agent harness underneath: github.com/xknk/deepseeker-code (also on npm as
deepseeker-code)
The most honest thing I can say about it: today I watched an agent complete a shift in my repo for less than the cost of a bottle of water — and one of its three tickets was spent correcting the previous shift's agent. Slow, steady, and cheap enough to be lazy about it. 🦥















