6 Days Late to My Landlord: I Built "Kal Karo" ('Do It Tomorrow') — a Local AI That Does the Dreaded Task For You
This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady What I Built In Urdu and Hindi, when you want a task to go away, you say "kal karo" — do it tomorrow. I say it a lot
This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
What I Built
In Urdu and Hindi, when you want a task to go away, you say "kal karo" — do it tomorrow. I say it a lot. To the landlord's email (six days old). To my Downloads folder (an archaeological site). To the meeting notes where somebody agreed to do something and nobody remembers who.
Every productivity tool I have tried responds to this by giving me more work: a better list, a smarter dashboard, a notification that says the quiet part louder. So for this challenge I built the opposite. KalKaro takes the dreaded list and does it — the boring 90% of it, today, on your own machine.
You write your tasks in plain words, one per line:
Reply to my landlord Mr. Rashid about the kitchen tap that has been leaking — his email came 6 days ago...
Sort out my Downloads folder at last — it is a mess of receipts, scans, screenshots and random files...
Make sense of my meeting notes from Tuesday's team call...
A local open-weight model breaks each task into micro-steps and labels every one DOABLE-BY-MACHINE or NEEDS-HUMAN (with the tiniest possible first action). Then KalKaro executes the machine steps itself, with three skills:
- Drafter — writes the actual reply you have been avoiding, ready to copy, paste and send.
-
Organizer — classifies, renames and sorts a messy folder into
Category/YYYY-MM/with clean names. - Digester — turns rambling notes into a summary, the decisions, and who-owes-what action items.
Everything lands in one done-for-you report: what was finished, the drafts themselves, the digests, measured timings — and for whatever is left, one tiny human step per task. KalKaro never sends, posts or deletes anything. Pressing send stays gloriously human, takes about four seconds, and is rather the point. The whole thing runs 100% locally on Llama 3.2 1B via Ollama: no cloud, no API key, no subscription, and your most embarrassing overdue tasks never leave your disk.
Results at a glance (from the real demo run below): 3 dreaded tasks finished · 5 of 5 files filed · 1 reply drafted · 1 set of notes digested · 0 failures · about 13 measured minutes of machine time on a contended 2-core VM — against roughly 30 minutes by hand for the notes task alone. The full payoff table, quality flaws included, is at the end.
Demo
No deployed link and no "coming soon" — KalKaro is a local tool, so the demo is a real run you can inspect and reproduce. The repo's demo/ folder holds the dreaded list, the messy folder and the messy notes; run-demo.sh executes the whole pipeline on a copy and saves the unedited transcript to demo/DEMO-OUTPUT.txt. Here is that run, condensed only by removing repetition:
▸ Task 1: Reply to my landlord Mr. Rashid about the kitchen tap…
⛨ guardrail: added the Drafter step the planner missed
✓ draft written → drafts/draft-1.md
done in 3m 8s
▸ Task 2: Sort out my Downloads folder at last…
⛨ planner failed (model call timed out after 150s (wall-clock limit)) — deterministic fallback plan: organizer only
✓ organiser: 5 file(s) moved
done in 4m 49s
▸ Task 3: Make sense of my meeting notes from Tuesday's team call…
⛨ guardrail: dropped a Drafter step — a notes task needs a digest, not a message
✓ notes digested → digests/digest-1.md
done in 5m 17s
The draft it wrote for the six-days-late landlord email:
Hello Mr. Rashid,
I wanted to follow up on my email from six days ago regarding the kitchen tap that has been leaking. I've been meaning to address this issue, but I've been putting it off. I'm now at a point where I need to apologize for the delay and ask for your assistance in sending a plumber to fix the problem this week. I would greatly appreciate it if you could provide a specific time for the plumber to arrive. I've been keeping track of the time, and I'm expecting the plumber to arrive sometime this week. I'm hoping this will be resolved soon, and I'm grateful for your understanding in this matter. I'm looking forward to hearing back from you and finding a solution to this issue. Thank you for your time and assistance.
Best regards
Not perfect — it muddles who emailed whom (it "follows up on my email", when Mr. Rashid's email is the one being answered) and breezily announces "I'm expecting the plumber to arrive sometime this week", which is the landlord's call to make, not the tenant's. But the apology is in there, the ask is in there, and it is sendable after a 30-second tidy. That tidy is the remaining human step, and the report leaves it to you under its first move: "Compose email."
The folder, before → after:
| Before | After |
|---|---|
IMG_4021.png |
Media/2026-10/img-4021.png (filed by filename — the model can't see photos) |
expense-export-sept.csv |
Document/2026-10/expense-export-sept.csv (classified from its own content) |
fix-login-bug.js |
Code/2026-10/fix-login-bug.js (by extension — no model call at all) |
receipt-coffee-shop.jpg |
Receipt/2026-10/receipt-coffee-shop.jpg (by filename) |
scan_003.pdf |
Invoice/2026-10/scan-003.pdf (recognised as an invoice from its own text — but it kept its scanner name this run) |
Five files, five filed in the right category — and note how the folder task got there: its planner call timed out, so a deterministic fallback plan (organizer only, no planner involved) did the filing. The notes digest is the honest weak spot of this run. The summary carries the big calls (landing page v2; discount until Oct 31) — and then repeats them, near-verbatim, in a second paragraph. The Decisions section itself came back empty. The nine action-item lines cover what is really four jobs: Sara's banner sizes twice, Dev's invoice chase four times under two different owners, the blog read-through given to the wrong person, two lines that invent owners for jobs the notes left unassigned — and Dev's image-compression job, the most concrete task in the notes, missing entirely. All of it, including the flaws, is in the transcript.
One more digest test, because the demo's notes are kind compared to real ones. I keep a nastier fixture: client call notes where the annual discount is explicitly left open — "annual discount could be 10% or 15%. Nadia will decide after finance reviews it. Nobody agreed a final discount on this call." An earlier build of the Digester filed that line under Decisions, stated as calmly as the settled items. That is the one sin a notes tool must never commit: presenting an undecided thing as decided is worse than missing it entirely, because somebody will act on it. So the fix is not a sterner prompt — it is a deterministic pass in code. Any extracted "decision" carrying an unresolved marker or an either/or figure is split out into an Open questions section, and the summary is checked for sentences that contradict the split. After the fix I re-ran that fixture three times end-to-end (between half a minute and just over two minutes a run): the discount never appeared as a decision again. Once the summary itself flagged it as unresolved; once it surfaced as what it actually is — an action item, "Nadia — decide on annual discount." The fixture ships in the repo as demo/notes-hard.txt (its task line is demo/tasks-hard.txt) and the three re-runs are written up in QA-RERUN-REPORT.md — the claim is checkable, not asserted. A 1B model will keep trying to tidy open questions into answers. A rule can simply refuse to let it.
Code
onyxailabs
/
kalkaro
KalKaro — a local AI agent that does the dreaded task for you (files, notes, drafts). Runs on your own machine with Ollama.
KalKaro
"Kal karo" is Urdu/Hindi for "do it tomorrow." It is also, not coincidentally, what I have been saying to the same three tasks for about a week.
KalKaro is a small local AI agent that takes the list of tasks you keep postponing, breaks each one into micro-steps, and then does the machine-doable 90% itself — today, on your own machine. What it leaves you is the tiny human step at the end: press send, glance at a summary, pick a morning.
It runs 100% locally on an open-weight model (Llama 3.2 1B via Ollama). No cloud, no API key, no subscription — and your dreaded tasks, including the embarrassing overdue ones, never leave your disk.
What it does
Give KalKaro a plain-words list of dreaded tasks:
Reply to my landlord Mr. Rashid about the kitchen tap that has been leaking — his email came 6 days ago
Sort…Plain Node (18+), zero dependencies beyond Ollama itself. The interesting files: kalkaro.mjs (planner, executor, routing guardrails, report writer), skills/drafter.mjs (refusal detection + voice), skills/organizer.mjs (few-shot classification + date grounding), skills/digester.mjs (decomposed extraction), and demo/DEMO-OUTPUT.txt (the proof). The full build log — every failure included — is BUILD-REPORT.md in the repo root.
How I Built It
Around the model, honestly. KalKaro's intelligence is Llama 3.2 1B Instruct (q4_K_M, ~800 MB) served by Ollama on localhost. I chose a 1B model on purpose: it runs on any laptop CPU, costs nothing, and keeps private tasks private. Then I spent the week learning what a 1B model actually needs around it — because the first versions were a mess, and each fix taught me something real:
-
Stream everything. My first end-to-end run died at exactly 5m 02s with
fetch failed— with non-streaming calls, Ollama sends nothing until generation completes, and Node's fetch gives up at 300s. The model was fine; the plumbing wasn't. - The grammar shapes JSON, not its length. Ollama's structured output gave me valid JSON — pretty-printed across 111 lines until it hit the token cap mid-string. Fix: demand single-line output, cap generation, and make the parse-retry ask for a much shorter plan instead of repeating the request that overflowed.
- Small models refuse and drift. Llama 1B declined to draft a landlord email ("I can't fulfill this request", and once, memorably, that the message "could be used to deceive or mislead"). It also writes in the third person about you, and invents dates. Fixes: concrete first-person prompts with a small example of the voice, a refusal detector with a plain-language retry, and a rule that a date in a new filename must literally exist in the source file or it gets stripped.
-
Decompose, then guardrail. One prompt asking for summary + decisions + action items reliably produced two sections and stopped — always dropping the action items. So the Digester makes focused calls per section and assembles the brief in code. And around the planner sit deterministic routing guardrails grounded in your own words: a task that never mentions a folder does not get an Organizer step; a notes task does not get a draft; code files file themselves by extension. Every guardrail prints a
⛨line in the transcript when it fires. The model proposes; the rules dispose; you can watch both.
Development happened on a shared 2-core VM that also renders my videos, which is why the demo's timings swing wildly. The run transcribed above took about 13 minutes wall-clock on a box whose load average spiked past 8 — heavy enough to time the folder task's planner out at 150s, which is why you can watch the fallback plan fire in the transcript. A day earlier, the identical demo on the same contended machine took 41 minutes; a single notes task on a warm, quieter machine today finished in 29 seconds. I left the timings in as measured rather than tidying them; on your own laptop, budget minutes — a 1B model is a tortoise, albeit a reliable one.
Why Does Open Innovation Matter?
Because the tasks on a dreaded list are exactly the data you least want in someone else's cloud. "I owe my landlord an apology and my rent conversation is six days stale" is not a prompt I want on a usage dashboard, metered by the token. An open-weight model on my own machine makes KalKaro possible at all: zero cost (a tool for postponers cannot itself be a subscription you postpone cancelling), total privacy by architecture rather than by policy, and — just as important — inspectable. Every trick in the How I Built It section exists because I could watch my own model's raw behaviour, retry it, re-prompt it and wrap rules around it without asking anyone's permission or paying for the privilege of debugging. Open weights turned "AI assistant" from a service I rent into a part I can build with. A part, notably, that works offline, on a train, on a laptop from 2019, in Muzaffargarh or anywhere else the cloud is far away.
My Agent Session
I built KalKaro with an AI coding agent as a pair, in this workspace, across one long day — and the session nearly didn't survive it: the development VM restarted often enough to kill four builder attempts mid-work (once mid-demo, wiping the temp folder). The countermeasure was unglamorous and total: a BUILD-REPORT.md checkpoint updated after every verified step, so any restart lost minutes, never the thread. That log ships in the repo, timestamps, failed runs and all. I don't have a DevRelay embed to offer — the build log is the session record, and I'd rather show you the real artefact than a polished replay.
The Lazy Payoff
Real numbers, from the demo run above (KalKaro's own report, unedited; timings measured on the contended dev VM — see the note in How I Built It):
| Dreaded task | Days postponed | By hand (planner's estimate) | KalKaro (measured) | Your remaining step |
|---|---|---|---|---|
| Reply to landlord about the leaking tap | 6 | no estimate | 3m 8s | Compose email |
| Sort out the Downloads folder | — | no estimate | 4m 49s | Open the folder and eyeball the new layout |
| Make sense of Tuesday's meeting notes | 7* | ~30 min | 5m 17s | Open the digest and star your action items |
*The planner's guesses are rough — it read "sitting there all week" as 7 days. The 6 days it got exactly right, because the task text said so and KalKaro takes the number from your own words when the planner drops it.
And the honest failure count, because a payoff table without one is marketing: in the two plans the planner returned it proposed 9 steps; 3 machine steps executed, none were marked prepared-only, and the routing guardrails had to correct the plan in 2 of 3 tasks — adding the Drafter step the planner forgot on the landlord task, and removing the one it invented for the notes. The third plan never arrived (150s timeout), and its task finished anyway on the fallback. The draft needed a human tidy (the who-emailed-whom muddle above). The digest was the run's weakest output, as detailed in the Demo section: a right-but-repetitive summary, an empty Decisions section, and nine noisy action lines for four real jobs. Zero tasks failed — but "did not fail" and "did it well" are different claims, and for the notes this run only earns the first. What KalKaro actually saved was not the minutes in the middle column — it was the activation energy. The reply existed. The folder was filed. The notes had a summary and names next to actions, two of them wrong. Each task went from "anxiety with no shape" to "one small step with a first move attached", and that, if you are the kind of person who says kal karo, is the whole game.
Slow and steady, indeed: the tortoise here is a 1B model on a laptop CPU, and it still finished the list before tomorrow.
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.