By Karl Mehta 2026-05-24 v0.1.32

Task Hub — Codex-style tasks, inside CodeNow.

Beta users were running CodeNow next to Codex because Codex had something CodeNow didn't: a single cross-project list of every task you've ever asked an agent to do, with its own git branch, its own status, its own follow-up thread. So they'd code in CodeNow and tab-switch to Codex to see "what was I working on?" That's the gap v0.1.32 closes.

What you'll see

A new tab on the left sidebar — sixth one, between Agents and the integrations rail. Open it and you get a cross-project list of every task you've ever started, grouped by project, with a status pill, a branch chip, and a relative timestamp. Click any row, and the editor area becomes a three-pane task detail view. ⌘⇧N anywhere creates a new one.

┌─ Sidebar · Tasks tab ────────────────┐ 📋 TASKS [+ New] │ ┌──────────────────────────────────┐│ │ │ Search tasks… ⌘⇧F ││ │ └──────────────────────────────────┘│ [All · 3] [codenow · 3] ━━ CODENOW ━━━━━━━━━━━━━━━━━━━━━━ Fix Cmd+K stale results 🌿 tsk-46d595770cf0 ●needs review 3s│ Migrate exec-agents to TS 🌿 tsk-3719bcf60171 ●needs review 3s│ Add JIRA OAuth scaffold 🌿 tsk-82c253ec56ef ●needs review 4s│ └──────────────────────────────────────┘

The branch chip is real. Every task gets its own git branch by default — codenow/tsk-<id> off whatever base you picked at creation time. Your working directory is untouched; the branch sits there waiting until you check it out from the terminal to do the actual work. If you toggle the "Create isolated branch" checkbox off in the new-task modal, the task lives on the base branch instead.

Why branch-per-task is the default

Three reasons we copied this from Codex:

If the project isn't a git repo, the branch toggle disables itself and shows an honest warning. If git refuses the branch op (dirty index, missing base), the task record still saves and you see the error inline. No silent failures.

The task detail view

┌─ EDITOR AREA — REPLACED BY TASK DETAIL ──────────────────────────────┐ Fix Cmd+K stale results [← Back] [Update ↑] [Discard] 🌿 codenow/tsk-46d595770cf0 → main · ●needs review · claude-opus-4-7 ├──────────────────────────────────────┬─────────────────────────────────┤ CONVERSATION FILES CHANGED YOU · INITIAL PROMPT No diff captured Quick-open results stay stale after switching projects. v0.1.33 ships the full per-file list + click-to-open [ Ask for follow-up changes… ] in Monaco. └──────────────────────────────────────┴─────────────────────────────────┘

Header at the top: title (editable in v0.1.33), branch chip, base-branch arrow, status pill, model badge, permission-mode pill, relative time, project name. Conversation pane on the left shows the initial prompt you wrote at task creation and (after v0.1.33) the recorded turns from the JSONL replay system that already underpins the Runs tab. Files-changed pane on the right will surface per-file diffs in v0.1.33.

The five status pills

StatusPillWhat it means
runningrunningAgent is still working
needs-reviewneeds reviewDefault after creation; agent finished, awaiting your call
mergedmergedBranch merged into base
discardeddiscardedBranch deleted without merge
failedfailedAgent errored out
Honest scope. The [Update ↑] and [Discard] buttons are visible but disabled in v0.1.32 — their tooltips say "ships in v0.1.33." That's the no-mocks rule applied to itself: no destructive git operations until the smoke matrix has had a release to settle without regressions. v0.1.33 wires both to real git merge / git branch -D.

Cross-project, by design

The task list is one global file (~/.codenow/tasks.json), so the sidebar can show every task across every project you've opened. The chip row at the top — All · 3 · codenow · 3 · xspan-api · 12 — lets you scope to one project or see everything. Sticky group headers keep you oriented when scrolling.

This is the part that makes the difference vs. "oh just check the Runs tab" — Runs is per-project. If you're switching between four repos like Karl does, you want one screen that says here's everything in flight, regardless of which window.

Migration from existing runs

First time you open the Tasks tab after upgrading, CodeNow scans every project's .codenow/runs/ directory and creates a task entry for each recorded run that doesn't already have one. They show up grouped under their project, default to status merged (best guess for "this is historical"), and are tagged backfilled: true internally. The migration is idempotent — re-runs are no-ops.

What also shipped — pair-programming fix

If you hit "Live edit failed: crdt timeout (renderer crdt.js not loaded?)" when starting a pair-programming session in v0.1.31, that's gone. Real cause: Supabase Realtime channel subscribe was awaited with no timeout and no error handling, so any non-SUBSCRIBED status (most commonly CHANNEL_ERROR from an expired JWT) hung the promise. The preload's 8-second safety net then fired with the misleading "renderer not loaded?" message.

Now: channel.subscribe handles every status, an inner 10-second timeout fires with the actual reason, and the preload safety was raised to 15 seconds. Users see toasts like "Live edit failed: Supabase Realtime subscribe failed (CHANNEL_ERROR): JWT expired" — actionable instead of mysterious. Full forensic walk-through in the v0.1.32 release notes.

And — full regression green

First release in months where the whole test suite is all-green end-to-end:

Every Task Hub state was also captured as a screenshot and visually inspected for errors, per Karl's no-mocks rule — empty state, new-task modal, list with tasks, detail view, back-to-code, search filter. No theater.

Get v0.1.32

Auto-updates from any prior version. Mac (Apple Silicon + Intel), Windows, Linux — all signed and notarized.