Codex Desktop list_threads needs project-scoped cursor pagination for safe automations
Environment
- ChatGPT/Codex Desktop:
26.818.21641(build6849) - macOS
26.6.2(build25G83) - Process architecture:
x86_64 - Naturally scheduled local automation
- Observed: 2026-08-20
Private project IDs, conversation IDs, account details, and local paths are intentionally omitted.
Summary
The app-facing list_threads tool cannot support correctness-sensitive project reconciliation because its surfaced schema exposes only a fixed result limit:
declare const tools: {
codex_app__list_threads(args: {
limit?: number;
}): Promise<unknown>;
};
It has no exact-project filter, page cursor, terminal completeness signal, or durable incremental checkpoint.
This is independently blocked by the scheduled-run hang in #35030, but even after that hang is fixed, a successful fixed-limit response cannot establish that all conversations in one ChatGPT Project were enumerated.
Reproduction
- Create a naturally scheduled automation that needs to inspect conversations belonging to one ChatGPT Project.
- Inspect the exposed
list_threadsschema. Onlylimitis available. - Attempt a bounded call. In the latest run,
list_threads({limit: 50})remained pending through four bounded waits and had to be terminated. - Reduce the limit or run interactively. A returned recent-task window still cannot be paged, filtered server-side to the exact project, or proven complete.
- Try to resume later from a durable cursor. No cursor or changed-since checkpoint is exposed.
Expected behavior
Provide a bounded, project-scoped enumeration contract suitable for scheduled automation. One possible shape is:
list_threads({
projectId?: string,
limit?: number,
cursor?: string,
changedSinceCursor?: string
}) => {
threads: ThreadSummary[],
nextCursor?: string,
complete: boolean,
checkpointCursor?: string
}
Required semantics:
- Prefer server-side filtering by exact ChatGPT Project ID.
- Support small bounded pages with an opaque continuation cursor.
- Return an explicit terminal/completeness indicator.
- Preserve stable conversation IDs, exact project ID, kind, and update timestamp.
- After a complete bootstrap, expose a durable cursor/checkpoint that returns only new or changed conversations.
- On timeout or partial failure, return a structured error without implying an empty or complete result.
Names are illustrative; equivalent semantics would solve the problem.
Actual behavior
- The tool schema exposes only
limit. - Results are a recency-bounded mixed inventory rather than a provably complete project inventory.
- There is no cursor for older pages.
- There is no durable incremental cursor.
- In natural scheduled runs, the call can also remain pending, as tracked in #35030.
Impact
A safety-conscious automation must fail closed:
- It cannot infer “no new conversations” from a timeout or partial recent window.
- It cannot advance a source checkpoint.
- It cannot claim source parity or completeness.
- It must remain paused even when repository identity and read/write capability are independently verified.
This blocks reliable, low-noise scheduled reconciliation of ChatGPT Project conversations without resorting to unsupported local database access or UI scraping.
Related issues
- #35030 — scheduled
list_threadscalls hang while interactive calls succeed. - #35377 — surfaced
querysupport can disagree with the runtime validator. - #25500 — project views can incorrectly imply no chats when older conversations fall outside the recent set.