Skip to content

Increase cap of sessions in VS Code extension #15368

Open

Description

@iqdoctor

What version of the IDE extension are you using?

26.5318.11754

What subscription do you have?

Pro

Which IDE are you using?

VS Code

What platform is your computer?

Linux

What issue are you seeing?

Codex VS Code Plugin Feedback

Evidence in local extension code:

  • /root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/index-BX_E-kXD.js.map
    • embedded source ../../src/feedback/feedback-command.tsx
    • embedded source ../../src/feedback/feedback-success.tsx

Environment

  • VS Code extension: openai.chatgpt-26.5318.11754-linux-x64
  • Bundled extension CLI: codex-cli 0.116.0-alpha.10
  • System CLI: /usr/bin/codex -> codex-cli 0.116.0
  • Host: remote VS Code server on Linux
  • Codex data dir: /root/.codex

Problems

1. Session list is capped too aggressively

With intensive Codex usage, the session/thread list in the VS Code plugin becomes incomplete. In my case the plugin initially showed only 50 sessions, then after local bundle patching it showed 100, and only after forcing auto-pagination it showed 313. This makes the sidebar/task history unreliable for real workloads.

Expected:

  • the plugin should either load all recent local threads needed for search/resume,
  • or clearly support pagination / load more in the UI,
  • or at minimum not silently stop at a fixed hidden cap.

Observed local code paths:

  • /root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/app-server-manager-hooks-DC8Cu72L.js.map
    • embedded source ../../src/app-server/app-server-manager-constants.ts:9
      • RECENT_CONVERSATIONS_PAGE_SIZE = 50
    • embedded source ../../src/app-server/app-server-manager.ts:1161-1181
      • refreshRecentConversations() requests thread/list with limit = RECENT_CONVERSATIONS_PAGE_SIZE * recentConversationsPageCount
    • embedded source ../../src/app-server/app-server-manager.ts:1298-1315
      • loadMoreRecentConversations() requests thread/list with limit: RECENT_CONVERSATIONS_PAGE_SIZE
  • /root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/index-BX_E-kXD.js.map
    • embedded source ../../src/sidebar/sidebar-electron.tsx:144
      • sidebar pulls local threads via useConversationsMeta()
    • embedded source ../../src/header/recent-tasks-menu/recent-tasks-menu.tsx
      • recent/local tasks UI renders what it gets; there is no visible explicit paging UX for local conversations there

Local temporary workaround applied:

  • runtime bundle patched in:
    • /root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/app-server-manager-hooks-DC8Cu72L.js
  • changes:
    • raised page size from 50 to 500
    • added auto-pagination during recent conversation refresh until nextCursor is exhausted or 500 items are collected

2. Lost titles without disk fallback

Some threads lose their title in the plugin/local state DB even though a valid thread name still exists on disk. This makes sessions effectively disappear from normal search/use in the plugin.

Concrete example:

  • thread id: 019ca226-b30c-7181-bdf0-62b891464a25
  • disk/session index had:
    • /root/.codex/session_index.jsonl
    • thread_name = "Worker"
  • but plugin/local DB had:
    • /root/.codex/state_5.sqlite
    • title = ''
    • first_user_message = ''

As a result, the CLI could still find the session as Worker, but the VS Code plugin could not reliably surface it by name.

Observed local code paths:

  • /root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/app-server-manager-hooks-DC8Cu72L.js.map
    • embedded source ../../src/app-server/app-server-manager.ts:1389-1415
      • upsertRecentConversationState() uses thread.name or persisted title cache
      • no fallback to session_index.jsonl, rollout JSONL, or recovery history when metadata title is blank
    • embedded source ../../src/app-server/app-server-manager.ts:1472
      • new conversation state gets title: persistedTitle
  • /root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/index-BX_E-kXD.js.map
    • embedded source ../../src/local-conversation/get-local-conversation-title.ts
      • fallback logic uses only:
        • conversationState.title
        • first turn input text
        • parent subagent prompt
      • there is no disk/index fallback

Supporting local evidence:

  • thread index on disk:
    • /root/.codex/session_index.jsonl
  • thread state DB:
    • /root/.codex/state_5.sqlite
  • rollout file exists:
    • /root/.codex/sessions/2026/02/28/rollout-2026-02-28T05-49-31-019ca226-b30c-7181-bdf0-62b891464a25.jsonl
  • recovery text exists:
    • /root/.codex/recovery/019ca226-b30c-7181-bdf0-62b891464a25/history.jsonl

Local temporary workaround applied:

  • repaired blank titles directly in:
    • /root/.codex/state_5.sqlite
  • source of repair:
    • first from /root/.codex/session_index.jsonl
    • fallback from rollout/history on disk
  • backup created:
    • /root/.codex/state_5.sqlite.bak-20260321-042851

Suggested fixes

Session list cap

  • Avoid hidden hard caps for local recent threads in the extension UI.
  • Either:
    • auto-page until all recent threads are loaded,
    • or expose an explicit local "load more" UX,
    • or use the existing full traversal path analogous to listAllThreads() instead of only the first recent page.

Lost title fallback

  • On recent-thread hydration, if thread.name is blank and the persisted title cache is blank:
    • check session_index.jsonl for thread_name
    • if still blank, derive a title from rollout/recovery first user text
    • write repaired title back into the local thread state DB/index
  • This should be a metadata-layer repair, not a UI-render-time disk read.

Short version

Two plugin issues become visible under heavy real use:

  1. local session list silently truncates because recent conversations are page-capped;
  2. blank local DB titles are not repaired from disk, even when CLI-visible thread names still exist.

I reproduced both locally and applied temporary workarounds, but both should be fixed in the extension/app-server metadata path rather than by local runtime patching.

019d0ddb-8fb3-7873-a5e0-688f9437ef61

What steps can reproduce the bug?

Uploaded thread: 019d0ddb-8fb3-7873-a5e0-688f9437ef61

What is the expected behavior?

Open Tasks in Plugin, see View All (50) - hard limited 50 records

Additional information

No response

Activity

  1. changed the title [-]Codex VS Code Plugin: Session list is capped too aggressively, Lost titles without disk fallback[/-] [+]Increase cap of sessions in VS Code extension[/+] on Mar 21, 2026
  2. added
    enhancementNew feature or request
    and removed
    bugSomething isn't working
    on Mar 21, 2026
  3. iqdoctor commented on Mar 21, 2026

    @iqdoctor
    Author

    Added focused follow-up comments to two related issues:

    Why this may help a coding agent process the duplicates better:

    • it gives a concrete constant and exact functions to inspect for the fix point
    • it separates a client-side visible cap from a deeper pagination / hydration boundary
    • it adds a validated local experiment, which narrows the search space
    • it turns the report from a generic UX complaint into a traced engineering bug

    What I intentionally did not do:

    • I did not comment on #14389, because it is already closed
    • I did not paste the same long note into every potential duplicate, to avoid diluting the signal
  4. iqdoctor commented on Mar 21, 2026

    @iqdoctor
    Author

    Codex VS Code Plugin Session Repair Notes

    Date: 2026-03-21

    Scope

    This note captures a repeatable workflow for debugging and hot-patching future Codex VS Code extension releases when:

    • the local session/thread list is silently truncated
    • sessions exist on disk but are missing or undiscoverable in the plugin because titles are blank

    This was validated on:

    • VS Code extension openai.chatgpt-26.5318.11754-linux-x64
    • bundled extension CLI codex-cli 0.116.0-alpha.10
    • system CLI /usr/bin/codex -> codex-cli 0.116.0
    • Linux remote VS Code server

    Symptoms Seen

    1. Hidden recent-thread cap

    Observed sequence:

    • plugin initially showed only 50 local sessions
    • after increasing the client page size, plugin showed 100
    • after forcing auto-pagination across nextCursor, plugin showed 313

    Conclusion:

    • there is a client-side recent-thread page size
    • there is also a deeper pagination boundary if the client does not continue loading

    2. Blank-title sessions

    Concrete example:

    • thread id 019ca226-b30c-7181-bdf0-62b891464a25
    • ~/.codex/session_index.jsonl still had thread_name = "Worker"
    • rollout file still existed on disk
    • but ~/.codex/state_5.sqlite had:
      • title = ''
      • first_user_message = ''

    Effect:

    • Codex CLI could still find the session as Worker
    • VS Code extension could not reliably surface it by name

    Primary Local Paths

    • extension bundle directory:
      • /root/.vscode-server/extensions/openai.chatgpt-*/webview/assets/
    • current runtime-patched bundle:
      • /root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/app-server-manager-hooks-DC8Cu72L.js
    • current sourcemaps:
      • /root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/app-server-manager-hooks-DC8Cu72L.js.map
      • /root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/index-BX_E-kXD.js.map
    • local Codex state:
      • /root/.codex/state_5.sqlite
      • /root/.codex/session_index.jsonl
      • /root/.codex/sessions/
      • /root/.codex/recovery/

    Root Cause Notes

    Recent-thread cap

    From the embedded sources in the sourcemap:

    • src/app-server/app-server-manager-constants.ts
      • RECENT_CONVERSATIONS_PAGE_SIZE = 50
    • src/app-server/app-server-manager.ts
      • refreshRecentConversations() requests thread/list with:
        • limit = RECENT_CONVERSATIONS_PAGE_SIZE * recentConversationsPageCount
      • loadMoreRecentConversations() requests thread/list with:
        • limit: RECENT_CONVERSATIONS_PAGE_SIZE
    • src/sidebar/sidebar-electron.tsx
      • sidebar uses useConversationsMeta()

    Interpretation:

    • UI is built from recent loaded conversations, not from the full on-disk session set
    • the extension does not automatically page through all local recent threads in this path

    Blank-title sessions

    From the embedded sources in the sourcemap:

    • src/app-server/app-server-manager.ts
      • upsertRecentConversationState() relies on:
        • thread.name
        • persisted title cache
      • it does not fall back to:
        • session_index.jsonl
        • rollout JSONL
        • recovery history
    • src/local-conversation/get-local-conversation-title.ts
      • fallback chain is:
        • conversationState.title
        • first turn input text
        • parent subagent prompt
      • no disk/index fallback

    Interpretation:

    • if recent-thread metadata loses title, the plugin can fail to surface a session by name even when disk data still exists

    How To Inspect New Releases

    1. Find the current hashed asset names

    find /root/.vscode-server/extensions/openai.chatgpt-* -type f | rg 'app-server-manager-hooks|index-.*\\.js\\.map|index-.*\\.js$'

    2. Check the embedded source map for the hardcoded page size

    python - <<'PY'
    import json
    p='/root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/app-server-manager-hooks-DC8Cu72L.js.map'
    with open(p) as f: m=json.load(f)
    i=m['sources'].index('../../src/app-server/app-server-manager-constants.ts')
    print(m['sourcesContent'][i])
    PY

    Look for:

    • RECENT_CONVERSATIONS_PAGE_SIZE = 50

    3. Check the live compiled JS bundle for patch needles

    node - <<'NODE'
    const fs=require('fs');
    const p='/root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/app-server-manager-hooks-DC8Cu72L.js';
    const s=fs.readFileSync(p,'utf8');
    for (const needle of [
      'let t=50*this.recentConversationsPageCount',
      '{limit:50,cursor:this.recentConversationsNextCursor',
      's.length>0&&(this.recentConversationIds=[...s,...this.recentConversationIds]),this.notifyAnyConversationCallbacks()}async hydratePinnedThreads'
    ]) {
      const idx=s.indexOf(needle);
      console.log('needle', needle, 'idx', idx);
    }
    NODE

    Quick Hot Patch For Future Versions

    A. Raise the recent-thread page size to 500

    Use the actual current hashed bundle path.

    node - <<'NODE'
    const fs=require('fs');
    const p='/root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/app-server-manager-hooks-DC8Cu72L.js';
    let s=fs.readFileSync(p,'utf8');
    const before1='let t=50*this.recentConversationsPageCount';
    const after1='let t=500*this.recentConversationsPageCount';
    const before2='{limit:50,cursor:this.recentConversationsNextCursor';
    const after2='{limit:500,cursor:this.recentConversationsNextCursor';
    if (!s.includes(before1)) throw new Error('missing before1');
    if (!s.includes(before2)) throw new Error('missing before2');
    fs.copyFileSync(p, p + '.bak-quickhack');
    s=s.replace(before1, after1).replace(before2, after2);
    fs.writeFileSync(p, s);
    console.log('patched', p);
    NODE

    B. Force auto-pagination until 500 items or no nextCursor

    This is what was needed after the simple 50 -> 500 patch still only surfaced 100.

    node - <<'NODE'
    const fs=require('fs');
    const p='/root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/app-server-manager-hooks-DC8Cu72L.js';
    let s=fs.readFileSync(p,'utf8');
    const before='s.length>0&&(this.recentConversationIds=[...s,...this.recentConversationIds]),this.notifyAnyConversationCallbacks()}async hydratePinnedThreads';
    const after='s.length>0&&(this.recentConversationIds=[...s,...this.recentConversationIds]);for(;this.recentConversationsNextCursor!=null&&this.recentConversationIds.length<500;)await this.loadMoreRecentConversations();this.notifyAnyConversationCallbacks()}async hydratePinnedThreads';
    if (!s.includes(before)) throw new Error('missing refresh tail');
    s=s.replace(before, after);
    fs.writeFileSync(p, s);
    console.log('patched refresh tail for auto-pagination');
    NODE

    C. Syntax check

    node --check /root/.vscode-server/extensions/openai.chatgpt-26.5318.11754-linux-x64/webview/assets/app-server-manager-hooks-DC8Cu72L.js

    D. Reload VS Code

    In VS Code:

    • Developer: Reload Window

    Blank Title Repair

    Goal

    Repair threads.title in state_5.sqlite from disk-backed sources:

    1. session_index.jsonl
    2. rollout JSONL
    3. recovery history.jsonl

    One-off repair script

    python - <<'PY'
    import sqlite3, json, shutil, re
    from pathlib import Path
    from datetime import datetime
    
    STATE = Path('/root/.codex/state_5.sqlite')
    BACKUP = Path(f'/root/.codex/state_5.sqlite.bak-{datetime.now().strftime("%Y%m%d-%H%M%S")}')
    IDX = Path('/root/.codex/session_index.jsonl')
    
    shutil.copy2(STATE, BACKUP)
    print('backup', BACKUP)
    
    idx_titles = {}
    if IDX.exists():
        with IDX.open() as f:
            for line in f:
                line=line.strip()
                if not line:
                    continue
                try:
                    obj = json.loads(line)
                except Exception:
                    continue
                tid = obj.get('id')
                title = (obj.get('thread_name') or '').strip()
                if tid and title:
                    idx_titles[tid] = title
    
    md_link_re = re.compile(r'\[([^\]]+)\]\([^)]+\)')
    
    def normalize_title(text: str) -> str:
        if not text:
            return ''
        text = md_link_re.sub(r'\1', text)
        text = re.sub(r'\s+', ' ', text).strip()
        if not text:
            return ''
        return text if len(text) <= 80 else text[:79].rstrip() + '…'
    
    def title_from_rollout(path: Path) -> str:
        if not path.exists():
            return ''
        try:
            with path.open() as f:
                for line in f:
                    try:
                        obj = json.loads(line)
                    except Exception:
                        continue
                    if obj.get('type') == 'event_msg' and obj.get('payload', {}).get('type') == 'user_message':
                        title = normalize_title(obj.get('payload', {}).get('message', ''))
                        if title:
                            return title
                    if obj.get('type') == 'response_item':
                        payload = obj.get('payload', {})
                        if payload.get('type') == 'message' and payload.get('role') == 'user':
                            texts = []
                            for part in payload.get('content') or []:
                                if isinstance(part, dict) and 'text' in part:
                                    texts.append(part.get('text', ''))
                            title = normalize_title(' '.join(texts))
                            if title:
                                return title
        except Exception:
            return ''
        return ''
    
    def title_from_recovery(tid: str) -> str:
        p = Path(f'/root/.codex/recovery/{tid}/history.jsonl')
        if not p.exists():
            return ''
        try:
            with p.open() as f:
                for line in f:
                    try:
                        obj = json.loads(line)
                    except Exception:
                        continue
                    title = normalize_title(obj.get('text', ''))
                    if title:
                        return title
        except Exception:
            return ''
        return ''
    
    conn = sqlite3.connect(STATE)
    cur = conn.cursor()
    cur.execute("select id, rollout_path from threads where title='' or title is null")
    rows = cur.fetchall()
    
    for tid, rollout_path in rows:
        title = idx_titles.get(tid, '')
        if not title and rollout_path:
            title = title_from_rollout(Path(rollout_path))
        if not title:
            title = title_from_recovery(tid)
        if title:
            cur.execute(
                "update threads set title=?, first_user_message=coalesce(nullif(first_user_message,''), ?) where id=?",
                (title, title, tid),
            )
    
    conn.commit()
    cur.execute("select count(*) from threads where title='' or title is null")
    print('blank_remaining', cur.fetchone()[0])
    PY

    Validation Commands

    Count blank titles

    sqlite3 /root/.codex/state_5.sqlite "select count(*) from threads where title='' or title is null;"

    Inspect a specific thread

    sqlite3 /root/.codex/state_5.sqlite "select id,title,first_user_message,cwd,source from threads where id='019ca226-b30c-7181-bdf0-62b891464a25';"
    rg -n '019ca226-b30c-7181-bdf0-62b891464a25' /root/.codex/session_index.jsonl

    Check how many repaired titles still look bad

    sqlite3 /root/.codex/state_5.sqlite "select count(*) from threads where title like '# AGENTS.md instructions%';"

    Notes

    • The quick repair filled blank titles fast, but some reconstructed titles may still be noisy if the only available on-disk source is a wrapped prompt payload.
    • A proper upstream fix should do read-repair in the metadata layer, not in the UI row renderer.
    • Extension updates will overwrite the patched webview bundle, so future versions need the same inspection + reapplication flow.

    Related GitHub Issues

    • head issue:
      • https://github.com/openai/codex/issues/15368
    • related comments added:
      • https://github.com/openai/codex/issues/14812#issuecomment-4102065616
      • https://github.com/openai/codex/issues/15060#issuecomment-4102065633
      • https://github.com/openai/codex/issues/15368#issuecomment-4102425406
  5. iqdoctor commented on Mar 22, 2026

    @iqdoctor
    Author

    Follow-up from 2026-03-22.

    The extension version was still unchanged on my machine:

    • openai.chatgpt-26.5318.11754-linux-x64

    I verified that the previous hot patches were still present in the active bundle:

    • 50 -> 500 page-size change in refreshRecentConversations()
    • 50 -> 500 page-size change in loadMoreRecentConversations()
    • auto-pagination loop over nextCursor

    Despite that, the visible local session count had dropped again, this time to 200 instead of the previously observed 313.

    That suggests the issue is deeper than just RECENT_CONVERSATIONS_PAGE_SIZE = 50. The more reliable workaround was to bypass the initial recent-page request entirely and make refreshRecentConversations() use the existing full traversal path:

    • listAllThreads({ modelProviders: null, archived: false })

    So the refined diagnosis is:

    • there is a visible client-side recent-page cap,
    • but there is also a deeper instability/boundary in the thread/list recent-loading path,
    • and listAllThreads() is currently a stronger workaround than only raising the page size and chasing nextCursor.
  6. iqdoctor commented on Mar 29, 2026

    @iqdoctor
    Author

    Follow-up: after another VS Code extension auto-update, I re-applied the same local runtime patch to the new bundle and the full thread list became visible again.

    Current extension version:

    • 26.5325.31654

    Patched bundle:

    • /root/.vscode-server/extensions/openai.chatgpt-26.5325.31654-linux-x64/webview/assets/app-server-manager-hooks-XL0eRatK.js

    Local workaround re-applied:

    • refreshRecentConversations() switched from the initial thread/list page to listAllThreads({ modelProviders: null, archived: false })
    • loadMoreRecentConversations() raised from 50 to 500

    Observed result after Developer: Reload Window:

    • the sidebar now shows 414 sessions again

    This is another data point that the store update simply overwrites the patched webview bundle, and that the underlying issue is still the same recent-thread loading path rather than missing local session data.

  7. iqdoctor commented on Apr 17, 2026

    @iqdoctor
    Author

    Follow-up: in a newer VS Code extension build, the underlying issue is still reproducible, but the recent-thread loading logic has moved to a different compiled asset/module.

    Current extension version:

    • 26.5415.20818

    Relevant asset now:

    • /root/.vscode-server/extensions/openai.chatgpt-26.5415.20818-linux-x64/webview/assets/app-server-manager-signals-Dcn6qX09.js

    In older builds, the patch point was in app-server-manager-hooks-*.
    In this build, the relevant patch points moved to the delegated recent-thread loader methods:

    • refetchThreadList(...)
    • loadNextThreadListPage(...)

    Local workaround re-applied successfully:

    • refetchThreadList(...) switched from the initial listRecentThreads({ limit: 50 * this.pageCount, cursor: null }) path to a full traversal through listAllThreadsRequest (lv(...) in the compiled bundle)
    • loadNextThreadListPage(...) raised from 50 to 500

    This looks like the same product bug, but it is useful to note that the implementation moved. That makes the regression easy to carry forward across releases even when the symptom stays identical.

  8. iqdoctor commented on Apr 21, 2026

    @iqdoctor
    Author

    Follow-up after another VS Code extension update: same symptom and same conceptual workaround, but the compiled asset/module moved again.

    Current extension version:

    • 26.5417.40842

    Relevant asset now:

    • /root/.vscode-server/extensions/openai.chatgpt-26.5417.40842-linux-x64/webview/assets/send-app-server-request-C98EYioR.js

    Previously the recent-thread loader had moved to app-server-manager-signals-*; in this build it is now bundled under send-app-server-request-*.

    The conceptual patch points are still the same:

    • refetchThreadList(...)
    • loadNextThreadListPage(...)

    Local workaround re-applied successfully:

    • initial refresh now uses the full traversal helper (mv(...) in this minified bundle, corresponding to listAllThreadsRequest)
    • load-more page size raised from 50 to 500

    So the underlying bug appears unchanged, but the implementation keeps moving between compiled assets. This is useful for any coding agent working on the issue because searching only the old bundle names will miss the current patch point.

  9. thephotocrv commented on Apr 24, 2026

    @thephotocrv

    I am seeing the same issue on macOS with Codex Desktop 26.422.21637 (CFBundleVersion 2056).

    The important part: local data is not missing. The threads exist in ~/.codex/state_5.sqlite, but Codex Desktop only loads a global window of recent threads and then projects appear incomplete or as if they had no chats.

    Current local evidence:

    • ~/.codex/state_5.sqlite has the expected project threads:
      • Crv_PM: 14 active threads
      • WebPhotoCRV: 8 active threads
      • AyudaCodex: 5 active threads
    • ~/.codex/.codex-global-state.json is not empty:
      • active_roots: 3
      • thread_titles: 27
      • thread_order: 27
    • ~/.codex/session_index.jsonl: 27 entries
    • Codex telemetry in ~/Library/Application Support/Codex/sentry/scope_v3.json repeatedly reports:
      • thread_count_total: 50
      • thread_count_loaded_recent: 50

    I also inspected /Applications/Codex.app/Contents/Resources/app.asar and found the recent thread loader starts with:

    pageCount=1
    refetchThreadList(...) -> limit: 50 * this.pageCount
    loadNextThreadListPage(...) -> limit: 50

    This matches the observed behavior: if a workspace/project has threads outside the initial global recent window, the Desktop UI does not show the complete project even though the local SQLite data is present.

    I tried the usual safe steps:

    • reinstalling Codex.app
    • clearing app cache / local app support
    • checking global-state and session_index
    • reorganizing project folders

    None of those fixed the issue because the underlying thread data was already present.

    Expected behavior:

    • When expanding a project/workspace, Desktop should fetch/list threads for that specific cwd/workspace, not only rely on the initial global recent-thread window.
    • Alternatively, RECENT_CONVERSATIONS_PAGE_SIZE should be configurable or much larger.
    • By project should not show incomplete projects just because their threads fell outside the initial recent window.

    This is a serious workflow blocker for projects with more than a handful of threads.

  10. thephotocrv commented on Apr 24, 2026

    @thephotocrv

    Additional local finding after deeper testing. This may help isolate the actual Desktop reindexing bug:
    the issue is not only the 50 global recent-thread limit. There is also a reindexing/source-of-truth mismatch.

    Root cause observed locally:

    Codex Desktop does not reliably render project thread visibility from state_5.sqlite or session_index.jsonl alone. The UI state appears to be derived from the mtime of the rollout-*.jsonl files under:

    ~/.codex/sessions/
    combined with the global recent-conversations preload limit of 50.
    
    Concrete reproduction:
    
    I had a project with 14 active threads in state_5.sqlite.
    All 14 had the same exact cwd.
    None were archived.
    git_branch, git_sha, and worktree-related fields were not different.
    Updating only state_5.sqlite updated_at / updated_at_ms did not make the hidden threads appear in Codex Desktop.
    Updating session_index.jsonl and .codex-global-state.json also did not make them appear.
    Codex Desktop reverted/recomputed the SQLite updated_at values on launch.
    The values it restored matched the filesystem modification times of the corresponding rollout-*.jsonl files.
    After updating both:
    SQLite updated_at / updated_at_ms
    the mtime of each corresponding rollout-*.jsonl
    The project immediately showed all 14 threads in the UI.
    So the effective UI source of truth seems to be:
    
    rollout-*.jsonl mtime -> reindex -> SQLite/session index -> UI
    or at least the rollout file mtime participates in reindexing strongly enough to override manual SQLite/index changes.
    
    This explains why users see projects with missing threads even when local data exists and SQLite counts are correct.
    
    Expected behavior:
    
    Project thread lists should be resolved by project/workspace cwd, not only by a global recent window.
    The UI should not report a project as empty or partially empty when valid local threads exist for that exact cwd.
    Reindexing should use a stable thread metadata source, not filesystem mtime as a hidden effective source of truth.
    If mtime is intentionally used, it should be documented and kept consistent with SQLite/session metadata.
    Requested fix:
    
    Increase the global recent conversations preload from 50 to at least 200.
    Ideally make it configurable, e.g. in ~/.codex/config.toml:
    recent_conversations_page_size = 200
    or allow an unlimited / “load all local project threads” mode.
    
    Even better:
    
    When expanding a project, query local threads by cwd / project root directly.
    Do not depend on whether those threads happen to be in the latest 50 global recent conversations.
    Add proper pagination/search for local project threads.
    Make “By project” actually load all local threads for that project.
    Current workaround:
    
    I created a local script that, with Codex Desktop closed:
    
    backs up state_5.sqlite
    backs up .codex-global-state.json
    backs up session_index.jsonl
    backs up the affected rollout-*.jsonl
    updates SQLite updated_at
    updates the corresponding rollout file mtime
    rebuilds session_index.jsonl
    limits visible projects to the active project plus a helper project
    After doing this, the project becomes visible again in Codex Desktop.
    
    This is not a real fix. It is only a workaround to force Codex Desktop to reindex hidden local threads.
    
    Please fix this in Desktop. A hardcoded global recent-thread window of 50 is far too low for real Codex usage, because many users create many threads due to context limits, not because they want fragmented project history.
    
  11. iqdoctor commented on Apr 24, 2026

    @iqdoctor
    Author

    Follow-up after another VS Code extension update: same symptom and same conceptual workaround, but the compiled asset/helper moved again.

    Current extension version:

    • 26.5422.21459

    Relevant asset now:

    • /root/.vscode-server/extensions/openai.chatgpt-26.5422.21459-linux-x64/webview/assets/app-server-manager-signals-DaIWbgQQ.js

    In the previous reapply, the relevant logic had moved under send-app-server-request-*.
    In this build, the active patch target is back under app-server-manager-signals-*.

    The conceptual patch points are still the same:

    • refetchThreadList(...)
    • loadNextThreadListPage(...)

    Local workaround re-applied successfully:

    • initial refresh switched from listRecentThreads({ limit: 50 * this.pageCount, cursor: null }) to the full traversal helper (ey(...) in this minified bundle)
    • load-more page size raised from 50 to 500

    So the underlying bug still appears unchanged, but the implementation keeps moving between compiled assets and helper names (lv(...) -> mv(...) -> ey(...)). That makes the regression easy to carry forward across releases, and it means searching only older bundle names will miss the current patch point.

  12. thephotocrv commented on Apr 24, 2026

    @thephotocrv

    Additional external confirmation: after another update, the same bug remains but the compiled patch target moved again.

    In extension version 26.5422.21459, the relevant logic moved to:

    webview/assets/app-server-manager-signals-DaIWbgQQ.js

    The conceptual patch points are still:

    • refetchThreadList(...)
    • loadNextThreadListPage(...)
    • global recent thread list limit around 50

    A local workaround reportedly changed the initial refresh from:

    listRecentThreads({ limit: 50 * this.pageCount, cursor: null })

    to a full traversal helper, and raised load-more page size from 50 to 500.

    This reinforces that the underlying bug is unchanged, but the compiled implementation keeps moving between builds. A local bundle patch is therefore not a maintainable solution.

    Please expose an official setting or fix project thread loading so project views query all local threads by project/cwd instead of depending on the latest 50 global recent threads.

  13. iqdoctor commented on Apr 25, 2026

    @iqdoctor
    Author

    Follow-up after another VS Code extension auto-update: the regression happened again, but this time the compiled asset/helper did not move.

    Current extension version:

    • 26.5422.30944

    Relevant asset:

    • /root/.vscode-server/extensions/openai.chatgpt-26.5422.30944-linux-x64/webview/assets/app-server-manager-signals-DaIWbgQQ.js

    Compared with 26.5422.21459:

    • asset family/name stayed the same: app-server-manager-signals-DaIWbgQQ.js
    • patch points stayed the same: refetchThreadList(...) and loadNextThreadListPage(...)
    • full traversal helper stayed the same: ey(...)

    But the store update still restored the original recent-thread behavior:

    • initial refresh was back to listRecentThreads({ limit: 50 * this.pageCount, cursor: null })
    • load-more was back to limit: 50

    Local workaround re-applied successfully:

    • initial refresh now uses full traversal through ey(...)
    • load-more page size raised from 50 to 500
    • node --check passes for the patched bundle

    This adds a slightly different data point: the bug/regression is not only caused by implementation moving between compiled assets. Even when the asset and helper remain stable across builds, the extension update overwrites the runtime bundle and brings back the hidden recent-thread cap.

  14. iqdoctor commented on Apr 25, 2026

    @iqdoctor
    Author

    Follow-up from the latest local validation on openai.chatgpt-26.5422.30944-linux-x64:

    The issue is not only the visible client-side cap. A naive local workaround that replaces the first refetchThreadList(...) page with the existing recursive full traversal helper (ey(...), internally paging thread/list at limit:200) can make startup worse for large local histories.

    Observed locally:

    • ~/.codex/state_5.sqlite has 1963 rows in threads.
    • Forcing initial refetchThreadList(...) through full recursive traversal caused the VS Code UI to stay cloud-only while local sessions were still being walked/hydrated.
    • A less blocking workaround was to use a larger first page and preserve cursor-based pagination:
      • refetchThreadList(...): listRecentThreads({ limit: 500 * this.pageCount, cursor: null }), then keep nextCursor = r.nextCursor
      • loadNextThreadListPage(...): limit:500

    Why this may help triage:

    • There are two separate boundaries: the current small initial/list page cap, and the deeper pagination/full-hydration behavior.
    • A robust fix probably needs incremental rendering/pagination rather than synchronously loading all local threads before the first local list notify.
    • The relevant current compiled symbols in this build remained refetchThreadList(...), loadNextThreadListPage(...), and helper ey(...) in app-server-manager-signals-DaIWbgQQ.js.
  15. iqdoctor commented on Apr 25, 2026

    @iqdoctor
    Author

    Follow-up: I opened a separate issue for the broader VS Code sidebar semantics that this cap/history bug exposed:

    Why this may be useful for agent triage:

    • it separates the hidden cap symptom from the desired CLI-like loading semantics;
    • it points to concrete current fix points in the installed extension build (refetchThreadList, loadNextThreadListPage, refreshRecentConversations, inline slice(0,Math.max(3,e.length)), and the View all ({total}) label);
    • it references the Codex CLI resume picker model (PAGE_SIZE = 25, updated-time sort, cursor/background loading, progressive search);
    • it calls out a protocol boundary: current ThreadListResponse has cursors but no exact same-filter total, so the UI should not present loaded rows as if they are total rows.

    I intentionally kept this as a cross-reference rather than duplicating the full spec into this thread, so #15368 can remain focused on the disappeared/truncated history symptom.

  16. interconnectedMe commented on Jul 8, 2026

    @interconnectedMe

    Truncation also a problem for me on long-running chat sessions with multiple compactions.

    Codex (gpt-5.5) tells me that it's an issue with VScode not handling either the compactions, or just the length of some of the chats.

    If I know what the last thing I saw was, or roughly where we were, Codex can find the session that is truncated and then I can read or Codex can summarize to pick up where we were.

    But can cause a little disorientation while I try to work out what's happened.

  17. gerashegalov commented on Jul 9, 2026

    @gerashegalov

    Confirmed on VS Code extension 26.5623.141536-linux-x64.

    The webview sidebar now has paginated/full-traversal paths, but the native VS Code chat-session provider remains capped. provideChatSessionItems() calls requestThreadList() once with:

    {
      limit: 50,
      cursor: null,
      sortKey: "created_at",
      archived: false
    }

    It maps only that response's data and never follows nextCursor. The provider is registered through vscode.chat.registerChatSessionItemProvider("openai-codex", ...).

    Expected: follow nextCursor incrementally, or implement load-more/progressive search. Sorting by updated_at would also better represent "recent chats".

    This appears to be a remaining extension-host code path after the sidebar pagination improvements, rather than an app-server storage limitation.

  18. cixiangtao commented on Aug 17, 2026

    @cixiangtao

    There is now a complementary unofficial, temporary workaround for users whose current-project sessions are crowded out by unrelated projects in the global VS Code Recent Tasks query:

    https://github.com/cixiangtao/codex-vscode-project-patch

    npx -y codex-vscode-project-patch

    Instead of increasing the global page size, this tool patches the Webview-originated thread/list bridge to include the active vscode.workspace.workspaceFolders paths as cwd. The app-server then returns the page for the current workspace roots, so unrelated repositories no longer consume the Webview task-list result window.

    This distinction is important:

    • It does not remove or increase the hard page cap.
    • It does not implement cursor pagination, progressive search, or blank-title recovery.
    • It intentionally does not patch the native vscode.chat.registerChatSessionItemProvider path described above; that provider can remain capped independently.
    • It only improves the Webview Recent Tasks case where global cross-project results make a bounded list less useful.

    The CLI is version/hash gated, creates and verifies an original-file backup, validates the patched JavaScript, and refuses unknown bundle layouts. Restore is:

    npx -y codex-vscode-project-patch restore

    It modifies the installed extension locally and does not redistribute the official VSIX. Extension updates normally replace the patch. This should be treated as a narrow stopgap while the upstream extension adds proper project-scoped loading plus cursor-based pagination across all history providers.

  19. evandrocoan commented on Sep 23, 2026

    @evandrocoan

    I reproduced this with Codex VS Code extension 26.917.61114 on Linux. An older conversation was still present locally but did not appear in VS Code because it fell beyond the 50 most recent conversations.

    Increasing the fetch limit alone was insufficient: the extension also truncated the fetched results with e.slice(0,50) before passing them to the history UI.

    I made a temporary workaround that raises the local history limit to 199, uses the extension’s existing pagination, and removes that second truncation for local conversations. After “Developer: Reload Window”, the missing conversation appeared.

    The patcher, test, and instructions are pinned to this commit:
    evandrocoan/dotfiles@bcae1e3

    The test covers the 199-conversation boundary and catches the original 50-result truncation. This patches the installed extension bundle, so an extension update can overwrite it. The patcher rejects bundle layouts it does not recognize; it should be reviewed and adapted for new extension versions rather than applied blindly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestextensionIssues related to the VS Code extension

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions