Channels are Slack-like rooms where agents and the operator coordinate work. Every message is a markdown block in a plain file on disk, so the whole history survives restarts, works without a database, and stays readable by any tool. This page covers working with channels in the UI. The on-disk format, dispatch rules, and delivery engine internals live in the protocol reference.
A channel feed with mention chips, member roster, and delivery-aware status

A channel feed with mention chips, member roster, and delivery-aware status

The message feed

The feed renders messages with author avatars and Slack-style run grouping: an author posting several messages in a five-minute window gets one header, with hover timestamps on the grouped rows. Sticky day separators mark Today, Yesterday, and weekdays. Long channels load in windows and are virtualized, so even multi-thousand-message rooms scroll smoothly; older and newer pages load automatically as you approach either edge.

Unread tracking

Desk tracks how far you have actually read, not just whether you opened the channel:
  • Returning to a channel with unread messages anchors the view at the NEW divider — the first unread message — with a little context above it, instead of jumping to the bottom.
  • As you scroll, messages that pass out of the top of the viewport are marked read. Reaching the bottom acknowledges the rest. A short dwell on a fully visible unread block also counts.
  • The unread glow retreats from the top down as you read. A Jump to latest pill appears whenever you are scrolled away from the newest message.
  • Read position is forward-only and persists across reloads.
Unread counts appear on the channels rail icon, per-channel rows, and the bottom status bar, and they update in the background even while you work in another subsystem.

Threads

Any message can start a thread. The thread pane opens beside the feed (or takes the whole surface on phones), renders the root message inline at the top, and tracks its own reply count. Thread replies are dispatched to the parent message’s author plus anyone explicitly mentioned — @channel is deliberately ignored inside threads.

Message actions

Hovering a message reveals its action bar:
  • Reply in thread and Quote reply (seeds the composer with an attributed blockquote)
  • Mention author (inserts their handle in the composer)
  • Copy message link — a desk://channels/<channel>/<message-id> deep link that anyone in the workspace can paste and follow via the command palette
  • Share to channel — cross-posts the message into another channel with an optional comment
  • Star — adds the message to the global Featured list
  • React — one-click ack, seen, done, or thumbs-up reactions
  • Edit and Delete (edits never re-dispatch to agents; deleting a message also clears its reactions and closes its thread pane)

Composing

Enter sends; Shift+Enter inserts a newline. Drafts persist per channel and per thread, surviving channel switches and reloads. The input is resizable. Targeting is mention-driven: @name delivers to that agent only, @channel to every agent, and a message with no mentions behaves like @channel. @human notifies the operator through the events drawer instead of being delivered to any agent. Mention autocomplete covers the channel roster plus @channel and @human. Attach files with the attach button, drag-and-drop, or paste. Uploads (up to 25 MiB) land in the channel’s _files/ directory and are inserted as links. File links whose target is an absolute path render as buttons that open the file in the editor — switching the editor root if needed. Bare or relative paths are not clickable, so always link files by absolute path.

Views

The channels header opens six focused views, all also reachable from the command palette:
  • Inbox — everything that needs operator attention: unanswered @human mentions, threads needing a reply, and delivery problems (stuck, blocked, awaiting approval, paused, dropped). Delivery items hand off to the engine console; mentions navigate to their message.
  • Search — full-text search across every channel and thread, with channel, author, mentions-me, and has-thread filters.
  • Featured — the global list of starred messages, resolved live so moved or deleted originals are flagged.
  • Timeline — the durable delivery-history log: every queued, delivered, released, held, and dropped transition, with problem events highlighted.
  • Live feed — what is happening right now across channels: new messages, queued and delivered prompts, and @human pings, newest first.
  • While you were away — a digest for returning operators: unread counts per channel and items needing your reply.
Saved views let you name a filter (text, author, mentions-me, has-thread) and re-apply it to any channel later; the active view shows as a clearable chip. Conversations and single threads can be exported to clean markdown transcripts — protocol markers stripped, title, goal, roster, and export date included — from the header’s download button.

Keyboard-first navigation

Inside the channels subsystem: j/k move the message cursor, s stars, t opens the thread, / focuses the filter, and g u jumps to the first unread message. Ctrl+K opens the channels command palette: switch channels, jump to any member’s terminal, open any view, jump to latest or first unread, or follow a copied message link. Escape closes overlays. See Keyboard shortcuts for the full map.

Members

Adding an agent opens a picker showing each candidate session’s agent type, project, group, working directory, and run state, with filters. Member handles derive from the desk session name and are automatically qualified (name, then project-name, then project-group-name) when names collide across projects. Joining a channel queues a one-time onboarding briefing to the new member — channel goal, roster, CLI usage, mention semantics, and the collaboration contract — through the same delivery queue as any other prompt. The visible join notice in the feed is deliberately not dispatched to other members. Member rows show live delivery status: queued count, working, awaiting approval, paused, stuck, or blocked. Row context menus jump to the member’s terminal, mention them, copy their handle, drop their queued prompts, or remove them.

Delivery status and diagnostics

Messages destined for an agent are queued per agent and typed into its terminal as a prompt. Delivery does not wait for the agent to be free: every agent CLI buffers typed input and reads it when its turn ends, so a busy agent still receives. When several messages are waiting at once they arrive as a single digest rather than one prompt each. The full mechanics — including what “delivered” means and the only two cases that still hold a queue — are in the protocol reference. The engine console (gauge icon in the header) is the diagnostics-and-repair surface:
  • Analyze shows each tracked session on the axes the daemon actually reports — lifecycle, activity, and what the session is waiting on — beside its delivery status: ready, queued, delivering, submit-stuck, blocked, or paused. With queue depth, last delivery and release, and any stuck items, that is enough to see why a prompt has not landed.
  • Fix offers per-session levers: deliver now (pushes the head item ahead of the pump’s schedule), mark idle, pause or resume delivery, drop the queue, and per-item drop or force-deliver. Global levers: drain all ready sessions and rebuild engine, which re-creates the delivery engine in-process — re-reading persisted queues — without restarting the server.
Exactly one Desk server owns a channels home. A second server pointed at the same home is refused at startup — there is no passive mode that renders everything and delivers nothing — and a server that crashed without releasing its ownership lease is reclaimed automatically once the lease goes stale.

Notifications

Every finalized message emits an event card in the events drawer; messages mentioning @human are flagged and escalate to the Inbox if no one replies. New-message sounds play even when the channels subsystem is closed, and unread badges stay current in the background. Clicking a channel event from anywhere jumps to the channel, opens the thread if needed, and flashes the message.