4. A reminder job, then run it
A todo list should nag you. We’ll add a background job that checks for overdue todos once a day and shows a warning.
Add the job
vsceasy job add --name dueReminder --title "Due Todo Reminder" --dailyAt "09:00"✓ Job "dueReminder" added.
+ src/jobs/dueReminder.tsjob add supports several schedule shapes — pick one:
| Flag | Fires |
|---|---|
--every "30s" | on an interval (30s, 5m, 2h, 1d) |
--dailyAt "09:00" | once a day at local time |
--on startup | on a VS Code event (startup, saveDocument, …) |
--onFile "**/*.md" | when matching files change |
The runtime registers the timer on activate and cleans it up on deactivate — you only write the work.
Fill in the work
The generated job is a stub. Replace its run to query overdue todos with the
same TodosRepo() the panels use, and warn if any are past due:
import { defineJob } from '../shared/vsceasy';import { TodosRepo } from '../models/Todo';
export default defineJob({ title: 'Due Todo Reminder', schedule: { dailyAt: '09:00' }, run: async (vscode) => { const now = Date.now(); const todos = await TodosRepo().findMany(); const overdue = todos.filter( (t) => !t.done && t.dueDate && new Date(t.dueDate).getTime() < now, ); if (overdue.length === 0) return;
const titles = overdue.map((t) => t.title).join(', '); vscode.window.showWarningMessage( `${overdue.length} overdue todo${overdue.length > 1 ? 's' : ''}: ${titles}`, ); },});Because the job and the panels share TodosRepo() and the Todo type, this is
fully type-checked — t.done, t.dueDate, t.title are all known fields.
Build and launch
Everything is wired. Build and open the Extension Development Host:
bun run launchThis builds the extension + webviews and opens a new VS Code window titled [Extension Development Host]. Open the Todos view from the activity bar to use the list and form.
Inside VS Code you can instead press F5 (after bun run dev) for a
watch-mode loop: edit a panel, reload the host, see the change.
What you built
Starting from an empty project, four commands produced:
- a typed, persisted
Todomodel (db init+model add), - a full list + form UI with typed RPC and an activity-bar menu (
crud add), - a daily overdue-reminder notification (
job add),
and bun run gen kept package.json and the registry in sync the whole way.
The CRUD step already gave us an activity-bar menu. The next steps go deeper into how that menu works and what else can dock inside it.
Next: menus — the navigation model →
Reference
- The mini-ORM — queries, indexes, and providers behind
TodosRepo(). - Typed RPC — how the host ↔ webview bridge stays type-safe.
- CRUD scaffolding — customizing generated fields via
crud.config.ts. - Publishing — ship your extension to the Marketplace.