Add cursors to `thread/read` in the codex app-server

Open 💬 6 comments Opened Mar 23, 2026 by PanicIsReal

What variant of Codex are you using?

App-Server

What feature would you like to see?

Developing for the app-server

Currently trying to stop mobile from serving 10+ MB of a thread read over a socket.

Please consider adding cursors to the thread read so you can do lazy loading / pagination / endless scrolling

Unless this already exists please enlighten me I would love to know.

Additional information

_No response_

View original on GitHub ↗

6 Comments

PanicIsReal · 3 months ago

Not sure if bumping your own post is allowed but im gonna justify it again as sending a large thread context on every single thread resume is assinine on a mobile connection, especially since the threads are provided oldest to newest messages, so you cant even simply check to see if your local cache has the latest message to trigger pulling more in. Theres literally no work around, and constantly sending 10+MB over a poor internet connection depending on location is frustrating.

PanicIsReal · 3 months ago

Hi hoping this will gain traction soon, I see people asking on X as well about it Tweet Example so while people do not seem to be coming here to ask for it, it's clearly in the back of some peoples minds. Again, trying to multi task in threads bouncing back and forth in larger threads sending MB's every time is archaic.

If I'm not allowed to continue to bump my own post let me know thanks.

robertmsale · 2 months ago

Updoot

I have a workaround, but this would be a good feature long-term

robertmsale · 2 months ago

Would like to add to this.

~~thread/read fortunately enough has an includeTurns: bool param so you can opt out of the outrageously large websocket frames if managed externally. But thread/resume has no such affordance. The app-server will gladly send tens or hundreds of megabytes with no cursor and no opt out. This is a pretty serious issue for threads especially if they include images or anything like that.~~

Correction: v0.125.0 adds paginated thread/resume and thread/fork. This satisfies my particular thing. @PanicIsReal perhaps this could also satisfy the issue! thread/resume is idempotent and a no-op on already running threads so it can be used as an alt to thread/read probably

rdylina · 2 months ago

+1. This is now blocking desktop too. I hit an 825MB local rollout where thread/resume took 252s and desktop then attempted a 405MB thread-stream-state-changed IPC payload. Pagination/cursors need byte limits as well as count limits; clients need “latest tail only” plus explicit older-page fetch.

rdylina · 2 months ago

Follow-up / PR offer: I read the contribution docs and understand external PRs are invitation-only. If the team thinks this direction fits, I’d be happy to take a stab at an invited PR for the open-source app-server side.

Conceptually, the fix I’d propose is:

  • in no case should opening a thread load the entire transcript into app-server + client state
  • open threads from metadata + the latest tail only, roughly the most recent 100-200 messages or a small byte cap, whichever comes first
  • lazy-load older chunks only when the user scrolls upward / explicitly asks for them
  • compact or summarize the old head for model context instead of treating the full durable transcript as active state
  • keep large tool outputs/artifacts behind references, not inline in normal thread state
  • add hard byte/count limits so thread/read, thread/resume, and stream-state snapshots cannot produce 100MB+ payloads
  • document that Desktop/IDE clients should use paged turns/items and never full-hydrate a completed thread just because it was clicked

The desktop side still needs closed-code changes, but the app-server can provide the safe bounded contract and fail gracefully when a client asks for full hydration of an oversized rollout.