Implementation walkthrough · 24 September 2026

Where Feed data comes from, and where it lives

Feed is a view of agent activity recorded by the Mac. The phone fetches and combines that activity from its connected Macs. Notifications are also a Feed input. The Notifications tab keeps its own read and dismissal surface, while Feed projects the same durable notification records alongside agent activity.

Code traced at 32a5891c772eeb3b3ce2db75dc8747be95ae84ed on task-ios-feed-tab. This maps the current feature branch. Its latest UI checks passed; newer main still needs reconciliation. PR 10218, author: Abdulaziz Albahar.

Direct answers

Source

Rows can come from notifications too

Hooks, provider plugins, wrapper telemetry, Codex Teams approvals, and the notification history store feed the timeline. A notification creates a Feed row with its notification UUID as the event identity. [1–4]

Mac

Incoming rows are saved on disk

The Mac app keeps a live store and appends incoming items and later mutations to ~/.cmuxterm/workstream.jsonl. Startup collapses repeated JSONL rows to the latest state for each event. [5–7]

Phone

A live mirror backed by Mac state

The phone refetches the authoritative rows after restart. Reply text and the Replied marker come back from the Mac because the reply is stored on the event record; local triage remains device-specific. Sign-in and pairing have their own saved state. [9–10]

Follow an event

Choose a path. These controls illustrate the inspected implementation; they do not send commands to an agent.

Agent integration

Structured events

Native hooks, plugins, wrappers, or the Codex Teams app-server bridge.

feed.push
Owning Mac

FeedCoordinator + WorkstreamStore

Validate the target, create a row, retain content, and increase the revision.

workstream.jsonl
Paired phone

Feed snapshot and UI

Fetch from each capable Mac, combine rows, and route actions to their owner.

feed.list · feed.text
Notification branch: agent lifecycle handling and actionable Feed events can also trigger notification history, native banners, or push delivery according to policy. The Notifications tab uses notification.feed.list and its own Mac history store. Agent Feed reads feed.list, which now combines Workstream rows with those durable notification records. Apple push delivery is only a delivery mechanism; the Mac history is authoritative. [3, 8, 11]

The phone communicates with the owning Mac over an authenticated connection. The transport chooses its direct or relay route. Authentication, discovery, and push can involve infrastructure; the inspected Feed path does not use a cloud database as its authoritative row store. “Mac-owned data” does not mean every network connection is infrastructure-free.

What can produce a Feed row?

ProducerWhat enters FeedLimit
Agent hooks through cmux hooks feedPermission, question, plan, tool, prompt, session, and stop events.Only events the provider integration emits. Installing cmux does not create a complete transcript for every agent.
Provider wrappers and pluginsWrapper telemetry adds session/prompt/stop activity. OpenCode’s plugin sends the same socket protocol; Pi supplies lifecycle/tool telemetry.The wrapper telemetry send is best effort, with short timeouts and swallowed errors. It has no durable Feed outbox on that path.
Codex Teams app-server watcherActionable command/file approval requests after Codex asks for user approval.Regular Codex hook permission events remain nonblocking telemetry. They do not imply this approval bridge is active.
Other supported event producersThe local socket accepts validated feed.push events; remote workspace integration can forward them.Admission and live target checks still apply. Provider parity is not established by a shared wire format.
Notification history / Apple pushNotification history is persisted on the Mac, and Feed projects each retained record.The notification UUID is the Feed event ID. Push delivery can be missed; a later feed.list refresh reads the Mac history.

Source trace: [1–4]. Provider hook ingestion was checked for Codex, Claude, OpenCode, Pi, Cursor, Grok, and Gemini. This is not proof that every provider supports the same permission/question/plan features.

The phone deliberately hides noise: standalone session starts/ends, user prompts, routine tool calls, and successful tool results. Prompt text can appear as context on another row. Stops, permissions, questions, plans, assistant messages, and failed tool results pass the host filter; the UI further shapes the presentation. [8]

What is persisted?

DataMacPhoneConsequence
Incoming Feed item and retained messageDisk + memory. JSONL append is asynchronous; write errors are ignored.In-memory snapshot of bounded previews.Phone restart needs a Mac fetch. Abrupt Mac exit can lose a queued write; there is no durable-write acknowledgement on this path.
Permission/plan/question resolution and expiryDisk + memory. Each mutation appends the latest WorkstreamItem version, and startup collapses rows by event UUID.Updated mirror while connected.Restart restores the latest decision or expiry. Waiting hook decisions remain process-local.
Terminal reply text + Replied markerText is pasted into the terminal, then stored on the exact WorkstreamItem named by feed_event_id when submission succeeds. The append-only record is replayed on startup.Rehydrated from the Mac's durable event record; no phone disk cache is needed for correctness.Every reply is tied to one event UUID, so a refresh or restart cannot move the Replied marker to another row.
Done / Needs Input overrideNo update to authoritative pending state.Local memory only.This is personal triage, not an answer to an agent request.
Full-text reader contentsReads the retained item in the current store snapshot.Loaded into sheet memory, no dedicated persisted cache.New reads need the owning Mac. Disk history outside the loaded snapshot is not fetched automatically.

Retention and limits

  • Mac startup restores the latest 300 persisted items.
  • Live ingestion caps the working store at 2,000 items. The separate Mac history loader can load older pages.
  • Mobile feed.list returns at most 200 visible items per Mac, fewer if the response-size limit requires it.
  • The phone combines up to 400 rows. There is no mobile older-history cursor here.
  • Full text uses 16 KiB pages with an 8 MiB phone limit.
  • The disk log has no automatic retention limit in this implementation; explicit Feed clear removes it.

Storage ownership and privacy

The default log path is scoped to the local OS user. It is not separated by app tag or Stack account, so development instances can restore history from the same file.

The persistence redactor covers tool/permission payloads. It does not generally redact stop response text or conversational context. Treat the retained content as potentially sensitive local data.

These are code findings, not a completed privacy or crash-recovery audit. Retention, account switching, deletion, and shared-file behavior need explicit release decisions. [5–7]

What happens when something disconnects?

Expected behavior inferred from the referenced state and persistence code. The live phone authentication/reconnect gate passed; these restart and loss scenarios have not all been exercised end to end.

Decisions before shipping

The implemented design is a useful live activity surface. A durable, cross-device conversation history would require additional work. The items below are findings and proposed acceptance criteria, not silently added implementation scope.

Decision / gapCurrent evidenceProposed acceptance criterion
Durable decisions and repliesIncoming items, resolution mutations, expiry, and terminal reply markers persist on the Mac event record. [6, 9–10]Restart both apps after a reply/approval. The row must preserve the correct result and cannot offer a duplicate action. Choose the authoritative persisted record.
Reliable delivery and deduplicationBest-effort telemetry can be lost. Stop deduplication uses a two-second match on device, workstream, provider, and reason, without the instance tag. [2, 10]Define stable provider event/turn IDs, retry guarantees, and acknowledgement. Repeated delivery produces one row; distinct rapid turns and sibling tags stay distinct.
Meaning of Repliedsubmitted: true confirms terminal submission. It is not a provider/model acknowledgement. [10]Either label this as submitted, or add evidence that the targeted agent accepted a new turn. Verify with each supported provider.
Failure recoveryThe composer closes on Send; failures in the current terminal reply path are logged without a visible retry flow. [14]Preserve the draft and explain failed delivery. A retry after partial paste must not type the reply twice.
History and ownershipNo phone disk cache or mobile history paging. Mac log is unbounded and shares its OS-user path. [5–10]Choose offline reading expectations, retention, cleanup, account/tag separation, and how old unavailable sessions are presented.
Transport compatibilityFull-text feature uses the existing feed.v1 capability; an older capable Mac can lack feed.text. [12]Version or negotiate the new read method, or require coordinated app updates. Older hosts currently produce a read failure rather than full text.
Release integration and verificationFull-text checks pass; newer main has conflicts and broader inherited checks are not green.Reconcile main, run the required checks, and verify real phone replies, deduplication, failure feedback, and restart recovery before merge/release.

What has been verified this round?

Passed

Reading UI

The hosted iPhone test verifies Markdown headings, lists, emphasis, links, and code in row previews and the full-text reader. It also checks inline expansion only for long text, retry, final paragraph, Close, Open, and Feed search. Inspected screenshots use test data.

UI test and attachments
Passed

Content and routing

Focused tests cover full text, Unicode pages, exact Mac ownership, authorization, Feed matching, and valid/deleted workspace or tab targets. Built CLI hook checks preserve complete supplied text for seven providers.

Focused test run
Mac, phone, and simulator connected

Current installation

The matching fmdblk apps at 20b38a26d7d are installed and signed in as aziz@manaflow.ai. The phone reconnects using its saved sign-in in 7,088 ms. The nearby simulator is updated and connected.

The spacing screen test catches the original 76-point gap and passes after the fix. The production Feed preview was also inspected on iOS 27. Live physical-phone Feed interaction remains a separate check.

The UI workflow’s separate conventions check remains red on inherited violations. The search coordinator unit run was blocked by an unrelated missing GhosttySurfaceWorkQueue symbol in the terminal test target; the production Feed search UI check passed. Mac download metadata and the older branch’s bundle-ID build setting needed task-local packaging corrections. iOS compiler output was isolated by tag/source after a stale Iroh header cache failed; the retry passed both packages. The existing task simulator was updated without booting another device. Physical-phone installation and a fresh saved-auth reconnect remain pending.

Code references

Links are pinned to the inspected revision. The session inventory tracks accepted scope separately from the proposed shipping work.

    Session decisions and capability inventory