Omniscio documentation
Browse all documentation
  1. Getting Started13
  2. Sessions & Agents115
  3. Inbox & Notifications59
  4. Projects & Tasks95
  5. Automation & Scheduling75
  6. Knowledge & Memory26
  7. AI Features60
  8. Integrations100
  9. Plugins & Marketplace33
  10. Cloud & Teams56
  11. Settings & Customization58
  12. Account & Billing28
  13. Troubleshooting84
  14. CLI & API Reference22
  15. Legal & Policies4
  16. Uncategorised22

Tasks (markdown outliner, in development) (part 5)

Every task can carry a little more than its text — all optional, all surfaced as small chips on the row only when set (so rows stay clean): An Importance dial — None / Low / Medium / High. Stored as a real column (importance, integer 0–3) so a later "what should I do right now" view can sort on it quickly. (Urgency was removed from the Tasks surface — its urgency column stays but is no longer shown.) A scheduled start date (startat) — "when I plan to start this," separate from the due deadline.

What it is

This is part 5 of the Tasks (markdown outliner, in development) page. It carries the next stretch of the material on that page, moved here because a single page is capped at 40,000 characters.

Where to find it

Reach this part through Tasks (markdown outliner, in development) — it lists every part and explains where the feature lives in the product. Everything below is reached from the same place.

How it behaves

Everything below is the behaviour, detail and edge cases that belong to this stretch of the Tasks (markdown outliner, in development) page.

Rich fields & fast capture

Every task can carry a little more than its text — all optional, all surfaced as small chips on the row only when set (so rows stay clean):

  • An Importance dial — None / Low / Medium / High. Stored as a real column (importance, integer 0–3) so a later "what should I do right now" view can sort on it quickly. (Urgency was removed from the Tasks surface — its urgency column stays but is no longer shown.)
  • A scheduled start date (start_at) — "when I plan to start this," separate from the due deadline.
  • An estimated time (estimated_minutes) — how long the task is expected to take. Type it naturally in the details pane — 30m, 1h, 1h 30m, 2h, or a bare number for minutes (90) — and it shows back tidy (1h 30m) both in the field and as a ⏱ chip on the row; junk or empty clears it. Bounded to 1 min…100 h. A recurring task carries its estimate to the next occurrence (a stable property, unlike the start date). Parse/format live in one shared helper (src/shared/tasks-v2-duration.ts).
  • Tags — free-form labels, stored in the task's metadata.tags JSON (no column).

You edit all of these in the details pane — opened from the row's sliders button, Cmd/Ctrl+;, or by clicking a due / importance / tags chip on the row — or set importance fast with the p key (a quick None / Low / Medium / High picker). Each field saves automatically as you leave it. Snooze in the details pane opens the same universal snooze palette as the h key (plus a Clear), not a raw date box. The importance dial uses a shared PriorityDial control (src/renderer/src/features/tasks-v2/PriorityDial.tsx).

Emphasis — bold, highlight & star a task

Three lightweight ways to make an individual task stand out, all per-task and all separate from the Importance dial above (which is for prioritization — emphasis is purely visual):

  • Star — flags the row with a ⭐ marker (a quick "favorite", distinct from priority).
  • Bold — renders the whole row's text in bold.
  • Highlight — gives the row a highlighter background in one of five colors (yellow, green, blue, pink, red). The colors are theme-aware — translucent, so they stay legible in both light and dark mode.

Set them two ways: in the task's details pane (a "Style" row beside the priority dial) or as quick toggles in a row's right-click / ⋯ menu (Star, Bold, and a color-swatch picker). Each saves instantly, shows in both the giant "All Projects" view and a single-project view, and Ctrl/Cmd+Z undoes it like any other edit. (Keyboard shortcuts for emphasis are not wired yet — they're an additive later step via the rebindable command registry.)

Under the hood these are presentation only — stored as bold / star / highlight keys on the task's metadata (the single source of truth for the keys, the 5-color allow-list, and the theme-aware classes is src/renderer/src/features/tasks-v2/tasks-v2-emphasis.ts). They drive no sorting or prioritizer and — unlike ctx / tags — do not appear in the tasks-v2.md mirror, so the export stays byte-identical. Both hosts render through the shared TaskV2Row, and the controls live in the shared details pane + row menu, so the two views can't diverge. Invariant emphasis-flags in the contract (.claude/memory/contracts/tasks-v2-contract.md).

Natural-language capture (the command line)

The dedicated "Add a task" box was removed from Tasks — you add tasks via each project's "+" (a master-view group header), the per-project outliner's always-present "Add a task" row, the empty-state's focused first-task field (on an empty list the cursor lands in an "Add your first task…" box — just type and press Enter; see Empty list opens ready to type), Enter on an existing row, or the in-list command line (press :). The command line still turns natural language into a task — type something like:

call vendor due friday #work !high

…and it parses the due date ("friday" → the upcoming Friday; dates lean future), the tag (#work), and the importance (!high) — also start <date> and an estimated time (~30m, ~1h30m, ~2h). (The ~ sigil does double duty by unit: ~ followed by a time — with a m/h unit — sets the estimate, while a bare ~1|2|3 / ~high is the shared parser's urgency, still dropped on the Tasks command line since importance is the only priority dial there. The two never collide because a unit-bearing ~30m can't parse as a ~1..3 level.) A date is never silently guessed (a wrong due date is a missed deadline). The natural-language dates come from the chrono library, loaded on demand so it never weighs down startup. The pure parser is src/renderer/src/features/tasks-v2/parse-quick-capture.ts (shared with Tasks).

Smart capitalization

As you type a task, the first word and the start of each new sentence are auto-capitalized — the same "smart" feel as the KMS notes editor. It is intelligent about what to leave alone: URLs, file paths, abbreviations (Dr., etc., i.e.), decimals (3.14), and U.S.-style initials all stay exactly as typed (as do already-capitalized words). It runs live as you finish each word in the per-project "Add a task" row (caret-safe — the transform only flips one letter's case in place, so your cursor never jumps to the end) and on blur when you edit an existing task's text (the contenteditable's caret is fragile, so the edit path tidies up only when you click away). A task you capture from the Ctrl+Space Quick Launch modal's Task tab is capitalized too — its saved text comes out exactly as if you'd typed it into the list. It is setting-gated — Settings → Lab → "Auto-capitalize task titles" (autoCapitalizeTasks, default on); turn it off and your text is stored exactly as typed. The rules (the URL/abbreviation/decimal/initials matrix) live in one shared module, src/shared/smart-capitalize-core.ts, used by Tasks, the Quick Launch task capture, and the KMS editor's AutoCapitalize extension, so they can't drift. The plain-string wrapper is src/shared/smart-capitalize.ts; invariant smart-capitalize in the contract locks that the transform is length-preserving and never flips a row blank.

Whitespace trimming

When a task is saved — whether you create it or edit an existing one — any leading or trailing whitespace is stripped (so " buy milk " is stored as "buy milk"). Spaces between words are left exactly as typed; this is a trim, not a re-spacing. Unlike smart capitalization it is not setting-gated — it always applies, and it happens at the save (persistence) layer, so every entry point gets it: the outliner, the : command line, the Quick Launch capture, and the CLI routes. It never leaves a task blank — a title that is only whitespace is treated as an empty edit and dropped, exactly like the "no blank tasks" rule. The invariant auto-trim in the contract locks this for both the create and edit save paths.

Add tasks at the top or bottom

New tasks added via the always-present "Add a task" row land at the top of the list by default — the newest task sits above the existing ones. You can flip this under Settings → Tasks → "Add new tasks at" (tasksV2QuickAddPosition, an enum 'top' | 'bottom', default 'top'): choose Bottom to append new tasks to the end instead (the pre-setting behavior). The control shows only when the Tasks Lab feature is revealed. Both "add a new task" affordances honor the setting — the "Add a task" row AND the "+" on a project's header in the all-projects view — so a new task lands in the same spot however you add it (before this, the project-header "+" always appended, so a top-preferring task landed at the bottom there). The POSITIONAL edits keep their own explicit positions and are unaffected: inline Enter (new sibling below), Shift+Enter (insert above), and multi-row paste. Under the hood top reuses the same insert-above mechanism as Shift+Enter: it resolves to a beforeId of the first row of the target list (scoped by list, since the giant view interleaves every project's rows in one order), so no backend or schema change was needed. The setting lives in src/shared/types/settings/tasks-v2-settings.ts; the invariant quick-add-position in the contract locks the default, the target-list scoping, and that every add-a-new-task affordance opts in through one shared reader.

Quick capture from anywhere (Ctrl+Space)

The global Quick Launch popup's Task tab captures a title straight into Tasks — filed in the default Inbox list — whenever Tasks is enabled (it falls back to the old v1 task list otherwise). It's the "catch a thought from anywhere, triage later" entry point, decided in the main process via the QUICK_LAUNCH_CREATE_TASK router so the storeless Quick Launch window never has to know which task system is active. See Quick Launch modal.

Sort & filter

The header's Filter funnel opens a popover that lets you sort the view (manual / importance / due date / start date) and filter it (minimum importance, or by tag); a dot on the funnel marks an active filter. Both are a view overlay only — they never rewrite your hand-arranged order, and filtering keeps a matched task's parent rows so the tree stays readable. (Urgency sort/filter was removed from the Tasks surface — the urgency column stays dormant.) The flatten powering it is flattenTasksV2 / useTaskTreeV2 (src/renderer/src/features/tasks-v2/task-tree-v2.ts), kept separate from v1's so Tasks (v1) is untouched.

All of this is additive and stays behind the Tasks Labs gate. (Dedicated link / document fields live in Context attachments — URLs, notes/markdown, attached files, and linked ContextDock bundles all attach there.)

Prioritizing AI — "Right now" + the daily check-in

"Right now" is hidden as of 2026-06-22. By user request, the Right now pill + panel were removed from the header and their automatic fetch was turned off, so the prioritizer's paid ranking is never called on its own (the description below documents how it works for when it's restored — a clean revert). The daily check-in and break it down are unaffected; each runs on a single click (no confirm pop-up) and stays under the shared daily cap.

Tasks can tell you the single highest-value thing to do next and run a short daily check-in. It reasons over the rich fields above (importance + urgency dials, due/start dates, and each task's time estimate when set) plus how much context a task carries. The estimate is context it may weigh (a quick win vs. a long haul) — in the check-in it surfaces a rough total only if you ask about time or the day's focus clearly runs long, never unprompted.

It's built to be cheap. A free, instant local scorer is the engine — it ranks your tasks with no AI at all (src/shared/tasks-v2-priority.ts), and that ranking always shows immediately. A cheap AI layer then refines it. The AI's verdict is cached and only recomputed when your tasks actually change (a new task, a changed dial/deadline, a completion), so it doesn't spend tokens on every screen refresh. If the AI is turned off, over the daily budget, or unavailable, everything quietly falls back to the free local ranking.

  • "Right now" (the header pill, which shows the pick's title inline → click opens a focused panel) — the one next action, with a plain-English "why" (factor chips like High importance · Due today, plus the AI's one-line reason). Act on it focuses the task, Not now cycles to the next-best, Re-rank asks the AI for a fresh take. Empty / all-done / all-snoozed / all-future show friendly copy, never a blank card. It's assistive — it suggests, you decide.
  • Daily check-in (the header's ⋯ More → Daily check-in) — an interactive conversation that reviews what's due and slipping and proposes today's focus. Starting it runs one bounded AI call (a single click, no confirm pop-up); then you can reply (each reply is one bounded AI call) and Accept the proposed focus. Today's thread is saved, so reopening it doesn't re-spend. It can also run automatically once a day at an hour you set — that scheduled run is off by default (opt-in).

Cost controls: a cheap model (Haiku 4.5 via OpenRouter), a shared daily $ cap across both surfaces (default $0.50, in the tasksV2AiDailyCapUsd setting), every call cost-tracked, and a setting to turn the AI off (falls back to the free local ranking). Settings live in src/shared/types/settings/tasks-v2-settings.ts: tasksV2RightNowAiEnabled (default on), tasksV2DailyCheckinEnabled (default off), tasksV2CheckinHour (default 8), tasksV2AiDailyCapUsd (default 0.5).

The whole surface is gated behind the Tasks flag and paid operations are IPC-only (never exposed over the CLI), so background agents and tests can't trigger spend. Channels (src/main/ipc/tasks-v2-ai-handlers.ts): TASKS_V2_RIGHT_NOW / TASKS_V2_RIGHT_NOW_RERANK / TASKS_V2_CHECKIN_GET / TASKS_V2_CHECKIN_RUN / TASKS_V2_CHECKIN_SEND / TASKS_V2_CHECKIN_ACCEPT, plus the TASKS_V2_AI_CHANGED push. The check-in thread persists in the tasks_v2_checkins table (migration src/main/db/migrations/20260608031242-tasks-v2-daily-checkins.ts).

This is Milestone M2 of the Tasks roadmap (the "minimum shippable" set is M1 + M2). It reasons over task data alone for now; an external "about-you" context system is a later, graceful-optional input. Not yet built: CLI read access to the prioritizer, and a Settings UI for the scheduled check-in's hour/cap knobs (the fields + scheduler exist; the on-demand check-in works without it).

M2 "Right now" status (feature-discovery audit F010): The "Right now" pill and its prioritizer panel were built and working, then hidden 2026-06-22 by user request. The backend prioritizer infrastructure (local scorer, AI ranking layer, IPC channels, daily cap, caching) remains intact. Re-enabling requires a product decision, not engineering work -- a clean revert of the header hide restores it.

Plan my day (M6)

Status: in development — additional opt-in toggle Settings → Lab → Plan my day (tasksV2PlanMyDayEnabled, default OFF), nested under the Tasks lab gate.

What it does

Plan my day is a smarter morning check-in that goes beyond reviewing what's due. Instead of a multi-turn conversation, it makes a single AI call, shows you a proposed plan — a focused task list, any new tasks it suggests adding, and optional "next action" splits for big items — and asks you to review and accept. Once you accept, the tasks are created and your focus list for the day is set.

How to use it:

  1. Open Tasks → ⋯ More → Plan my day (only visible when the toggle is on).
  2. The AI thinks for a moment, then shows its proposal: a message, a suggested focus list, any new tasks, and any breakdowns.
  3. Review the proposal — you can adjust the focus list and new tasks before accepting.
  4. Hit Accept to commit the plan. New tasks land in your Inbox; split next-actions are created as children of the parent task; Today's plate is arranged automatically from the accepted focus (same as accepting a daily check-in — you shouldn't need to click "Re-arrange today").

The AI uses your AI Coaching "About you" profile (when AI Coaching is enabled) to personalize the plan — it reads how many items you like to focus on, your standing priorities, and any notes you've added about yourself. That profile grows over time: each time you accept a plan, the app learns how many tasks you're comfortable with today.

Cost: one AI call per morning, drawn from the same shared daily budget as the daily check-in ($0.50 default, in Settings → AI → Tasks daily cap). No charge if the plan cannot be generated — a free local fallback is shown instead.

How it works (for AI readers)

Toggle gate. Plan-my-day behavior is only active when tasksV2PlanMyDayEnabled is on. When off, the IPC handler returns an error immediately — no AI is called and no spend occurs. The classic M2 check-in (CHECKIN_RUN / CHECKIN_SEND) is unaffected.

Open → single AI call → proposal. openPlanMyDay builds a CheckinContext (overdue, due-today, top-picks, total-open count), injects two briefs into the hidden system half of the prompt:

  • Planning brief — derived from the user's TaskV2PlanningProfile (preferred item count, granularity, standing priorities, freeform notes); null when the profile is absent or all fields are blank.
  • Coaching brief — reads the AI Coaching core profile, gated by isUnreleasedFeatureVisible('ai-coaching', settings), fail-open (any DB error → null), truncated at COACHING_BRIEF_MAX_CHARS = 2000. The coaching brief is injected ONLY into the system half and never into the user turn, displayText, or the conversation mirror.

The AI returns one JSON object: { message, focus, newTasks, splits, profileDelta }. parsePlanProposal (pure, no IO) validates it: routes through extractJson (handles fenced-JSON blocks), filters out focus/split ids not in the eligible set, caps arrays at MAX_FOCUS = 8 / MAX_SPLITS = 8 / MAX_NEW_TASKS = 10, and returns null on a missing/empty message or unparseable input. A null result triggers buildLocalPlanOpening (free, local fallback using the priority scorer's top picks). A newTask may also carry an optional estimatedMinutes — coerced by the shared clampEstimatedMinutes (whole minutes, 1..6000; a non-number / below-min / missing value is dropped) and written onto the created task at commit. The system prompt tells the model to set it (and to note the focus's rough total) only when the user asks about time, never unprompted — the estimate field is exposed to the AI, not volunteered by it.

Atomic commit. commitPlanMyDay runs one SQLite transaction: (1) create new tasks in the default Inbox list; (2) create split next-actions as children of their parents, inheriting the parent's list; (3) set proposed_focus_json to the REAL ids of the final focus set (existing + newly-created, stale ids re-validated and dropped); (4) upsert the planning profile; (5) stamp accepted_at; (6) clear proposed_plan_json; (7) arrangeTodayPlate for the check-in's date so the accepted focus lands on Today (parity with interview-accept). A mid-commit failure rolls back entirely — no orphan tasks. A second commit on the same checkin id is a no-op (accepted_at guard).

Profile learning. The tasks_v2_planning_profile table (single row, id 'default') stores preferredItemCount, preferredGranularity, standingPriorities, aboutFreeform. On commit, preferredItemCount is set to finalFocus.length — but only when > 0 (an empty/abandoned plan never overwrites the existing count with 0). An explicit profileDelta.preferredItemCount from the AI response takes priority over the derived count. The profile is readable and editable via the profile-get / profile-update channels.

Shared check-in row. Plan-my-day and the classic M2 check-in share the same tasks_v2_checkins row per date, but they key on independent signals so both can run on the same day: the classic check-in short-circuits on its message thread, while plan-my-day short-circuits on the stored proposal (proposed_plan_json) and does not write to the message thread. Opening the classic check-in first no longer blocks plan-my-day from generating a proposal, and vice versa.

IPC channels (all requireTasksV2Enabled()-gated, then plan-my-day toggle-gated):

Channel String Notes
TASKS_V2_PLAN_OPEN tasks-v2:plan-open Open / generate today's plan
TASKS_V2_PLAN_COMMIT tasks-v2:plan-commit Atomically commit the reviewed plan
TASKS_V2_PROFILE_GET tasks-v2:profile-get Read the planning profile
TASKS_V2_PROFILE_UPDATE tasks-v2:profile-update Upsert or clear the planning profile

All four channels are classified deferred-no-route in the CLI-parity manifest (consistent with the sibling check-in AI channels); promoting them to real CLI routes is a noted follow-up.

About-you view. The planning profile (preferredItemCount, preferredGranularity, standingPriorities, aboutFreeform) is surfaced to the user as an editable "About you" panel in the Tasks UI. It is the user's own data, always editable and clearable.

Contract: all invariants + locking tests: .claude/memory/contracts/tasks-v2-contract.md → "Plan My Day (Milestone M6)".

Related

The overview, the other parts, and everything else worth reading next all sit on Tasks (markdown outliner, in development).

Last verified 2026-09-23