---
title: Tasks (markdown outliner, in development) (part 3)
---
# Tasks (markdown outliner, in development) (part 3)

## What it is

This is part 3 of the [Tasks (markdown outliner, in development)](tasks-v2.md) 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)](tasks-v2.md) — 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.

### Keyboard: two modes (writing vs command) (continued 3)

**Snoozing tucks the task into a "Snoozed" section.** Once a task is snoozed into the
future, it leaves the list and collects under a single collapsible **⏰ Snoozed (N)** row
pinned at the bottom — so the list stays focused on what's actually actionable, while the
count tells you at a glance what's parked. **Open the section** to see each snoozed task rendered **just like a regular task row** — it's
**numbered** (1./2./3., the same as the list above), shows its full text, its wake date on the usual
alarm-clock chip, and a "+N sub-tasks" count if it has any. Its **🕐 clock header lines up in the
same column as those task numbers and the add-row's "+"**, so the section reads as part of the list
instead of sitting off to the side. To bring one back early, open the row's **⋯ menu** and choose
**Wake now** — the old always-on button is gone, so the rows stay calm and read like any other task.
When the snooze time passes the task **returns to its place in the list on its own** — and Omniscio
also drops a reminder in your **Inbox** so you don't miss it (see [Deadline & snooze reminders](#deadline--snooze-reminders)). If every task in a list is
snoozed, the section still shows (with an "all snoozed" note), so nothing is ever out of reach. The
consolidated **"All Projects"** view now behaves the same way — each project group carries its own
collapsible **⏰ Snoozed (N)** section at its bottom (same numbering + the ⋯ **Wake now**). These
snoozed tasks used to stay inline in that view as a slim ⏰ stub; they're now tucked into the
section like everywhere else.

**A task that came back is marked so you can see it was snoozed.** When a snooze time
passes and the task returns to the list, it carries a small **alarm-clock icon** (the same
one the rest of Omniscio uses for snooze) instead of the old "⏰ Yesterday"-style stale date. If
it's been snoozed **more than once**, a **×2 / ×3** badge rides beside the icon, and
**hovering** lists every snooze — each as "Snoozed Jul 1 → until Jul 5" (both the moment you
snoozed it and the wake time you picked). A still-**waiting** task is unchanged — it keeps
its "Snoozed until Friday" wording so you know when it's back; only the emoji was swapped for
that same alarm-clock icon. This history is recorded per task on every genuine snooze (editing
an already-set snooze's time or clearing it doesn't inflate the count) and is capped at the 25
most recent; tasks already snoozed when this shipped are backfilled with one entry so they read
right immediately. Undoing a snooze restores the count too, so it can never drift. Stored in
the `tasks_v2.snooze_history_json` column; the invariant + tests live in the contract
(`snooze-history` in [`.claude/memory/contracts/tasks-v2-contract.md`](/.claude/memory/contracts/tasks-v2-contract.md)).

**Fold a task that has sub-items.** Any task with sub-items shows a small **chevron (▸/▾)**
just to the left of its number (so the arrow hugs the item) — click it (or press **`F`**, or use the right-click **Collapse sub-items**
row) to fold its subtree out of sight; a quiet count shows how many items are tucked away, and
folding again unfolds them. The fold is **remembered across restarts** (it's saved like the
collapsed-project state), works in **both** the giant "All Projects" view and a single-project
list, and keyboard navigation skips folded rows. It only changes what's on screen — it never
moves, edits, deletes, or exports a task — and a folded parent is still fully covered by
whole-project actions (its hidden children still count). Drilling into or adding a sub-item under
a folded task automatically unfolds it so you always see what you just touched, and while a filter
is active folding is paused so a filtered-in match is never hidden.

The command line reuses the **same plain-English reader** that parses a typed capture
line ("call vendor due friday #work !high") when you _create_ a task, plus a small
phrase layer for "high priority" / "move to <list>" / "done" — so dates
("tomorrow", "next week", "in 3 days"), priority, and tags all just work,
and a line it can't read is shown back to you (nothing is written on a misread).
**Removing isn't a typed command** — a bare `Delete` (or `Ctrl/Cmd+Delete`) archives the task (reversible, like checking it off),
so a typed line can never destroy a task. New keys only fire when a task is highlighted
and you're _not_ mid-typing, so they never eat your keystrokes; v1 Tasks is untouched.

This keyboard drives **both** views the same way — the **default giant "All Projects"
view** and a **single-project filtered view** — because both mount one shared
implementation (`useTaskV2CommandKeys`). In the giant view the focus nav steps across
project groups, Alt+Shift+↑/↓ reorders the task up/down — **and at its sibling-group edge a nested
(child) row nests into the visually-adjacent SAME-PROJECT item** (move-down → first child of the item
below, move-up → last child of the item above; depth preserved), while a **top-level** row at a
project's top / bottom edge instead **carries into the neighboring project** (move-down → top of the
next project, move-up → bottom of the previous), and a **multi-selected block** at that edge crosses together as a set (appended to the target, one undo) — and **Tab/Shift+Tab — or the OneNote
aliases Alt+Shift+→/← — indent/outdent the focused row (or, with multiple rows selected, the WHOLE selected block together as one undo) within its own project** (scoped so neither indent nor a child's nest ever crosses projects); only
**Backspace-merge and drill-in** differ (no-ops in the merged view — see
[The giant default view](#the-giant-default-view--all-your-tasks-in-one-list)). In the giant
view the up/down nav **also stops on each project name (header)**, so you can act on a whole
project — see [Select a project & act on the whole thing](#select-a-project--act-on-the-whole-thing).

While your cursor is in the Tasks list, the list **owns its keys**: Omniscio's app-wide
shortcuts stand down for these bare keys (and for **Ctrl/Cmd+Z** / **Ctrl/Cmd+Y**, which run
the list's own **universal undo / redo** — see [Archive & universal undo](#archive--universal-undo)), so a
command-mode key never _also_ fires an app-wide action behind the list — exactly how the
Mind Map and Notes panels work. App-wide combos that aren't list keys (Ctrl+1-9 jump to a
project, Ctrl+T new session) still work from the list. **Ctrl/Cmd+K is now a list key** —
it inserts a link (see the keyboard table) rather than opening global search from Tasks,
the same way the Notes editor claims Ctrl+K for its own insert-link.

### Keyboard: two modes (writing vs command) — Caught — AI suggestions in their own view

When one of your agent sessions ends, a quick AI pass reads its transcript for follow-up tasks
you still owe and stages them as **suggestions** — nothing files itself. They live in their own
**Caught** entry in the project rail (with a count of how many are waiting); the entry appears
only while there are suggestions to review, and opens a plain **numbered list**, just like a
normal task list (this replaced the old strip that used to sit above the list).

Each row shows the suggestion, a quiet link back to the session it came from, a small **category
chip** (the project it will file into, editable), and — on the row you're pointing at or have
focused — **Approve ✓** and **Dismiss ✕**. **Approve** turns it into a real task in the chip's
project; **Dismiss** asks to confirm and stays **undoable**. At rest a row reads as a clean
numbered item, so the list never feels like a form.

It's keyboard-first, so you can clear it without a mouse: **↑** / **↓** (or **j** / **k**) move
between suggestions, **Home** / **End** jump to the first / last, **Enter** approves the focused
row (into its chip's project), and **Delete** opens the Dismiss confirm. The keys act **only while
the row itself is focused**, so typing in the category chip is never hijacked; the active row
shows a focus ring, and after you approve or dismiss, focus moves to the neighbouring suggestion
rather than being lost. Clear the last one and a friendly "you're all caught up" note takes its
place (`TaskV2CaughtView.tsx`).

**Control what gets caught.** Under **Settings → Tasks · Caught** (find it via Settings search)
you can turn catching off entirely, or give it **guidance** — tell the AI, in your own words, what
counts as a follow-up worth catching ("only things I still owe someone", "skip anything about
code"). The guidance steers which suggestions are kept but can't break the feature (the format it
returns stays fixed). Catching can also be limited to sessions from chosen projects (empty = every
session, so it never silently stops); that project picker is a small follow-up for now.

**Catching is selective by design.** A session is scanned only when **you actually typed in it** —
purely agent-driven sessions (background lanes, cron and recipe runs, peer-messaged workers) are
skipped entirely, so the agents' own to-do chatter never lands in Caught (and no AI call is spent
on them). A scanned session stages **at most 8** suggestions across three detection layers — up to 3
explicit (Layer 1), 3 implicit action items (Layer 2), and 2 pattern-based (Layer 3) — and most
stage none. The bar is a real next step **you** own, never the agent's own workflow steps (running
tests, merging a branch, re-running a session…). A suggestion you've already seen in the last two weeks — kept, dismissed,
or still pending from another session — won't be staged again, so five sessions on the same piece
of work can't each re-suggest "send Sam the deck".

**Suggestions re-check themselves, so the list doesn't go stale.** The most common reason a good
suggestion gets dismissed is simply that you already did it — the work closes long before you next
open the lane. So when a later session is scanned, the AI also looks at the suggestions still
waiting here and flags any the transcript shows you've since finished. A flagged row is **not**
removed: it sinks to the bottom of the list, renders faded under a "Looks already done since this
was caught" line, and shows the quote it based that on — so the top of the lane is only what's
still genuinely live, and a wrong guess is visible instead of silently trusted. You still click,
and **Approve** on a flagged row clears the flag (keeping it means you disagreed). This costs no
extra AI call — it rides the scan that was already running — and it never touches anything if
there's nothing waiting.

**Older suggestions fade out, but nothing is lost.** Suggestions older than 30 days are
automatically hidden from the active Caught list so the lane stays focused on recent, actionable
items. They are **not deleted** — they remain in the database and are still findable. When any
suggestions have aged out, a subtle banner at the bottom of the list shows how many were hidden
and links to **Ask Omniscio**, where the user can search past sessions for the task they're
looking for and re-add it.

### Cut & paste a task

Move a task with **Ctrl/Cmd+X** (cut) then **Ctrl/Cmd+V** (paste) — the same cut/paste you
know from files. Cut is a **move**; **Copy** (Ctrl/Cmd+C or the ⋯ / right-click **Copy** row) now
pastes too, as a **duplicate** — the original stays put and a copy lands where you paste, into the
same project or any other (a brand-new one included). Cut and copy share one clipboard (arming one
clears the other), and both paste the same way (below the highlighted row, or into a project
heading):

- **Ctrl/Cmd+X** marks the highlighted task (or a multi-selection) to move. With **multiple
  rows selected**, only the **topmost** selected tasks are cut — a parent+child selection
  keeps the child's nesting under the parent (same rule as Finish / Move). The row dims and
  gets a dashed outline and a
  small **✂ cut** tag (hover it for the paste/cancel hint). **The task does not move or vanish** — if
  you never paste, nothing changes (cut only _marks_).
- **Ctrl/Cmd+V** moves the cut task(s) to **right below the highlighted task — in every view.** A
  single-project list, the **All Projects** giant view, and moving a task **between** projects all
  land it directly under the highlighted row now (carried into that row's project when they
  differ). Nesting under a cut parent is preserved. The cut mark then clears.
- **Copy → paste is a DUPLICATE.** Copy a task (**Ctrl/Cmd+C** or the **Copy** row), then paste it
  (Ctrl/Cmd+V / **Paste here** / onto a project heading) to drop a **copy** in that spot — the
  original is untouched, so you can paste the same task into several projects, or into a brand-new
  one. Unlike a cut, a copy **stays** on the clipboard after pasting (paste it again) and survives
  even if you later archive the original. Copy carries the task's **own line** (not its sub-items),
  matching **Duplicate** (Ctrl/Cmd+D).
- **Paste into a fresh blank row.** After you copy or cut task(s), you can press **Enter** to add a
  new task and then **Ctrl/Cmd+V** — Omniscio drops the copied/cut tasks into that spot and clears
  away the empty new-task line, so the paste lands exactly where you started the new task. (Typing
  anything into the row first, or having nothing on the clipboard, keeps Ctrl/Cmd+V a normal text
  paste.)
- **Onto a project HEADING instead** (All Projects) — drop the cut task straight INTO a project,
  even an **empty** one (appended, since a heading has no task to sit below). Two ways: with the
  keyboard, land the cursor on **another project's heading** and press **Ctrl/Cmd+V**; with the
  **mouse or on a phone, just CLICK that project's heading** while a task is cut — the click drops
  it in instead of folding the project (and a collapsed target opens so you see it land). That
  click is how you fill an **empty** project without a keyboard. Clicking a project you can't move
  into — the synthetic **(Unfiled)** heading, or the task's **own** project — just folds it as
  usual (and pasting a task onto itself is a no-op). With nothing cut, clicking a heading folds it
  exactly as before.
- **Prefer a picker? Press `V`** on a task to choose the destination project from a small menu — the
  same as the ⋯ / right-click **Move to project**. Handy in a single-project view, where there's no
  other project on screen to paste onto.
- **Esc** cancels a pending cut; cutting another task moves the mark; archiving or deleting the
  cut task clears it. A failed or not-allowed paste **keeps** the mark so you can retry.
- It also lives in the **⋯ menu and the right-click menu** as **Cut** and **Paste here**, so it
  works with a mouse and on a phone (no Ctrl key there). The keys (cut / paste / move-to-project)
  are **rebindable** (Settings → Keyboard Shortcuts → Tasks) and show in the `?` cheat-sheet.
- Precise within-project paste needs the **manual sort with no filter** (the same rule as drag /
  Move up-down — under another sort the on-screen order is just a view); if you're sorted or
  filtered, Omniscio tells you instead of dropping the task somewhere misleading. While you're _typing_
  in a row, Ctrl/Cmd+X/V stay the normal text cut/paste.

### Paste a link onto selected words → a hyperlink

Select some words in a task and **paste a link** (any `http(s)` URL) — the selected words
turn into a **clickable hyperlink** to that address, instead of the raw URL landing as plain
text beside them. It's the same gesture every notes app and chat box uses: highlight
_the spec_, paste `https://…`, and the row now shows _the spec_ as a link. Works in both the
"+" quick-add row and when editing an existing task; undo with **Ctrl/Cmd+Z**.

- **On an existing task the row drops straight back to its rendered view after the paste**, so
  you see the finished clickable link immediately instead of the raw `[words](url)` markdown
  source. (In the "+" quick-add row the text stays as you type and becomes the link on Enter.)
- It only kicks in when you have text **selected** and the clipboard is **just a URL**. Paste
  a URL with **nothing selected** and it drops in as an ordinary (still clickable) link; paste
  plain text and nothing special happens — your paste is never hijacked.
- Want to type the label yourself, or add a link without selecting first? **Ctrl/Cmd+K** opens
  the Insert-link popover (see the shortcuts table). The paste gesture is just the fast path
  for the common case.
- Non-web schemes (`mailto:`, `ftp:`, `javascript:`) are never turned into a link.

### Edit a link you already added

Got a link in a task and need to fix where it points or change its wording? **Right-click the
link** and pick **Edit link**. A small box opens **pre-filled** with the link's current address
and text — change either, hit **Save**, and just that one link is rewritten in place (the rest of
the row is untouched). Like every other link edit, it's **Ctrl/Cmd+Z**-undoable.

- **Edit link** sits right next to **Copy link** in the menu that pops up when you right-click a
  link — so a link's own right-click menu is where you copy it OR edit it.
- It finds the exact link you clicked even when a row has several, and even when a pasted-URL
  link's on-screen text was shortened to keep the row tidy (the full address is still there to edit).
- This is a **Tasks** thing — links in chat and the inbox keep their usual right-click menu.

### A bare link → its title

Add a task whose text **is just a link** — a **YouTube/Vimeo video** or **any other web page** — and,
a beat later, it becomes a **clickable link labeled with the page's real title**:
`https://youtu.be/dQw4w9WgXcQ` turns into _Rick Astley - Never Gonna Give You Up_, and a bare
article / GitHub / docs link turns into that page's headline. Under the hood it's stored as a markdown
link (`[title](link)`) and the row renders task text as markdown, so you get the readable title **and**
keep the click-through — never dead, un-clickable text. The raw link is always kept **inside** the
titled link, so nothing is ever lost, and **Ctrl/Cmd+Z** snaps a just-pasted link back to raw.

**It fires no matter how the link got there — including links already in your list.** Paste a
**video** link into the "+" row or a task title and you get an instant spinner + Ctrl+Z; type any
link, or hit Enter before the title loads, and it still gets titled a beat later (titling is keyed off
the **saved task**, not the typing box). Links you **already had** — added before this feature, dropped
in by an agent, or created any other way — now get titled automatically **when the list loads** (a
one-time, per-session background pass). And for any bare-link row you can **right-click** (or open its
⋯ menu) and pick **Get link title** on demand.

- It only fires when the task text **IS the whole link**. A link dropped into the middle of other
  words is left alone, and non-web schemes (`mailto:`, `data:`, …) aren't touched. Twitter/X isn't
  auto-titled from a paste (a tweet has no "title" that reads as a task).
- While a title loads a **small spinner** shows in the row's trailing edge; if the fetch fails or
  times out (offline, a private/blocked page, a page with no title), it **quietly keeps the raw
  link** — no error popup, and the link is still a perfectly good task.
- It's **free and safe** — a **video** title comes from YouTube/Vimeo's public oEmbed (with an
  `og:title` page fallback for Vimeo's firewall); **any other page's** title comes from the same
  **security-hardened** fetcher the chat link-preview uses (it blocks private/internal addresses,
  follows redirects safely, caps size + time, and is rate-limited). Both run in the main process (the
  renderer can't make outbound calls) and cache results, so a re-load never re-hits the site.
- **The backfill never disturbs you.** It tries each link **once per session**, never re-touches a
  link it already titled, keeps the raw link on any failure, and — importantly — **doesn't touch your
  Undo history**, so Ctrl+Z always undoes _your_ last edit, not a background titling.
- **Never clobbers what you wrote.** The title lands only while the row still holds exactly that link;
  edit it in the meantime and the title is quietly dropped so your text wins. Key files:
  `store/tasks-crud-slice.ts` (`resolveLinkTitleForTask` + the create-time net + `backfillLinkTitles`),
  `video-title-paste.ts` (`detectVideoUrl` + `detectBareUrl`), `useVideoTitlePaste.ts` (the paste
  hook), `ipc/tasks-v2/video-title.ts` + the shared `link-preview` fetcher (main). Invariants:
  `tasks-v2-video-title-paste-contract.md` (`create-net-keyed-off-persisted-task`,
  `manual-get-link-title-action`, `backfill-is-session-once-and-undo-free`: the create-net, the
  "Get link title" action, and the load-time backfill).

### Paste an internal link → attach it to the task

Copied a **link to a session** — or to a specific **comment/message** inside one (the "Copy link"
on a session's menu, or "Copy link to this message")? Or a link to a **project**, a **chat
message**, a **KMS note**, a **super prompt**, a **mind map**, a **setting**, a **shared
conversation**? **Paste it into a task** and that entity is **attached to the task** — the same
kind of link the "Attach" picker makes — instead of the raw `omniscio://…` address landing as
text. It appears under the task's 📎
[Context attachments](#context-attachments) (click the chip to open it), and a toast with **Undo**
takes it right back.

- **On a task you're editing**, it attaches the instant you paste and the raw link is
  dropped. **In the "+" add-a-task row**, pasting a link fills the row with a **label** (session
  name / project name / a friendly noun like "Chat message") as a starter title and attaches it
  **when you press Enter** to create the task (type your own title over it if you'd rather). On a
  **focused task in command mode**, paste it straight onto the task the same way.
- A link to a **comment** attaches its **parent session** (there's no separate "attach a comment");
  session and project links attach as rich session/project context items, and **any other internal
  link** attaches as a clickable link item that opens the entity when clicked. Older `agentmc://…`
  links work too.
- It only fires when the clipboard **is the whole link** — a link pasted into the middle of other
  words is left alone, and a normal web/video link still does its own thing (see
  [A bare link → its title](#a-bare-link--its-title)). Already attached? It won't add a duplicate.
- No new setting — **Undo** is the off-switch (same as the bare-link titling above). Key files:
  `internal-link-paste.ts` (`parsePastedInternalLink`), `attach-pasted-internal-link.ts` (resolve
  the label → attach), `view-mode-paste.ts` (command-mode Ctrl+V onto a focused task), `TaskV2Row.tsx`
  / `TaskV2NewTaskRow.tsx` (the two edit surfaces), reusing the shared `attachSessionToTask` /
  `attachContextItemToTask`; url-kind items open in-process via `openAppLink` → `DEEP_LINK_OPEN`.
  Invariants: `tasks-v2-internal-link-paste-contract.md`.

### Archive & universal undo

**Finishing** a task marks it **done** and files it into **Archived** in one step —
completing and clearing it off your list together (think email **Archive vs. Trash**;
Delete still exists separately).

**Two outcomes, so Archived reads as a real ledger.** **Finish** says you did it.
**Drop** files the task away _without_ marking it done, for the things that stopped
mattering rather than got completed. Both clear the task and its sub-tasks off your list;
only the record differs. Drop is on the row's **⊘** button, the ⋯ and right-click menus,
the bulk bar, and **Shift+X** (**X** finishes, **Shift+X** drops). Undo restores the exact
outcome — a dropped task that you undo and redo comes back **dropped**, never quietly
finished. A **recurring** task that you _drop_ creates no next occurrence: dropping ends
the series, where finishing rolls it forward.

The **Archived** area badges every item **Done** or **Dropped**, with a filter to see just
one. Anything archived before this shipped is badged a neutral **Archived**: back then
archiving always wrote "done", so that flag can't tell whether you finished the task or
abandoned it, and the ledger won't claim an outcome it cannot know.

You finish a task **four ways**, all equivalent (they finish the task _and its
sub-tasks_):

- **Check the box** — the primary gesture. The row **smoothly collapses + fades** (~0.2s),
  is marked **done**, and tucks into Archived. (Under reduced-motion or low-power mode the
  collapse is skipped and the row finishes instantly.)
- **Middle-click** (the mouse's middle button) anywhere on a row — the fast power
  shortcut (Omniscio suppresses the browser's middle-click scroll "compass" so the gesture is
  clean); **right-click** opens the row's full action menu, where **Finish** is one of the options.
- The **Finish** row in a focused task's **⋯** menu (works on touch + keyboard).
- The **`x`** or **`e`** key on the highlighted task (command mode).

The **first** time you finish a task, a small **"Item complete! Use Ctrl+Z to undo."** toast
teaches you the shortcut; after that, finishes are silent (no repeated toast noise).
Finished tasks **leave your lists, counts, and the `tasks-v2.md` mirror** and
collect in a browsable **Archived area** — open it from the **"Archived"** entry pinned at
the bottom of the project rail (it shows a count of what's inside) **or** the header **⋯
More → Archived**. It opens as a **dedicated tab that takes over the main area** — your
active task list and the **"Add a task"** box are hidden while it's open, so finished items
never linger beneath it; click **Done** (or pick a project in the rail) to return. Inside,
items are **grouped by project**, with a **project filter** dropdown to show just one
project's archive, and each row shows **when it was archived** (the exact time on hover).
Each row's **Restore** button sits on the **left** and appears **on hover** (always visible
on touch); Restore brings the task back **active and unchecked** (if a task's original
parent is gone, Restore returns it to the top of its project so it never dangles).
**A bare `Delete` — or `Ctrl/Cmd+Delete` — archives here too.** `Ctrl/Cmd+Delete` used to be a
separate soft-delete that stranded the task (no toast, not browsable), and a bare `Delete` did
nothing; both now land in Archived like every other remove gesture. The bare `Delete` works only
in command mode (never while editing a row's text) and never on a project heading, so it can't
wipe a whole project — and it's `Delete` only, not `Backspace`.

**Universal undo — `Ctrl/Cmd+Z`.** Every change you make in Tasks — add, rename,
check-off, archive, **delete**, reorder, indent, move-to-project — can be undone with
`Ctrl/Cmd+Z`, and you can keep pressing it to walk back through your recent changes
(**no step limit**). It is a **real** undo: it puts the data back in the database (so it
sticks), not a screen repaint. A continuous run of typing on a row counts as **one** undo
step — so undoing a rename reverts the whole edit at once, never one letter per press. One honest limit: undo history is **per session** — it
resets when you quit and reopen Omniscio (surviving a restart is a separate, later feature).
While you're _typing_ in a row, `Ctrl/Cmd+Z` is the normal text undo; the task-level undo
runs in command mode (a highlighted, non-editing row) — and a **mouse-only** archive
(middle-click, the checkbox, or the ⋯ menu) keeps keyboard focus on the list so `Ctrl/Cmd+Z`
lands right after it, including from the **"No tasks yet"** screen when you archive your last
task. (Under the hood every action records its exact inverse and replays it as a real
operation — v2 only; the older Tasks list and Tasks are untouched.)

**Redo — `Ctrl/Cmd+Y`.** Anything you undo, you can **redo** with `Ctrl/Cmd+Y` (or
`Ctrl/Cmd+Shift+Z`) — it re-applies the change you just took back. Like undo it has **no step
limit**, so you can walk all the way forward again, and it's a **real** redo that persists to
the database. Starting a **new** change clears the redo trail (the standard "once you do
something new, there's nothing left to redo" rule). Redoing a typed word re-applies the whole
word at once, and redoing an added task or a finished **recurring** task brings back the
**same** row / the **same** next occurrence — never a duplicate. While you're _typing_ in a
row, `Ctrl/Cmd+Y` is the normal text redo; the task-level redo runs in command mode, exactly
like undo.

## Related

The overview, the other parts, and everything else worth reading next all sit on [Tasks (markdown outliner, in development)](tasks-v2.md).
