Skip to content

🩹 Restore archived chats access from the main Codex UI #27207

Open

Description

@richa65-personal

Summary

Archived chats need to be accessible from the main Codex UI, not hidden under Settings → Archived chats.

This appears to be a regression/removal: a user reports this was available from the main UI roughly two weeks ago, and now there is no obvious way to browse all archived chats from the main sidebar. If the user does not remember the chat name/title, search is not enough.

Current behavior

  • Archived chats are effectively hidden in Settings → Archived chats.
  • The main sidebar does not provide an obvious Archived view/section.
  • Accidental archive feels like the chat disappeared.
  • Recovery is not discoverable unless the user already knows the settings location.

Expected behavior

Please restore/add archived chat access to the main UI:

  • Add an Archived section/view in the main sidebar.
  • Add a command-palette action such as Show archived chats.
  • Make search clearly include archived chats or provide an obvious archived filter/badge.
  • Show an Undo archive toast immediately after archiving.
  • Keep Unarchive available from the thread menu inside the archived-chat list.

Why this matters

Archive is a normal chat-management action, but recovery is currently too hidden. Users who accidentally archive a chat and do not know its title need a direct way to browse archived chats from the primary navigation.

Environment: Codex Desktop on macOS.

Activity

  1. added
    enhancementNew feature or request
    appIssues related to the Codex desktop app
    sessionIssues involving session (thread) management, resuming, forking, naming, archiving
    on Jun 9, 2026
  2. github-actions commented on Jun 9, 2026

    @github-actions
    Contributor

    Potential duplicates detected. Please review them and close your issue if it is a duplicate.

    Powered by Codex Action

  3. Swich1987 commented on Jun 12, 2026

    @Swich1987

    +1. A concrete related use case: from Settings > Archived chats, it should be possible to open an archived chat in a read-only view to inspect its contents before deciding whether to restore/delete it. Opening it for inspection should not unarchive it as a side effect.

  4. joshka commented on Jun 13, 2026

    @joshka

    Another +1 for moving this out of Settings. Settings > Archived chats is a strange place for a normal visibility/navigation mode, and it makes archived chats feel lost unless you already know where to look.

    The affordance I would expect in the desktop app is a normal menu/view control, for example View > Show Archived Chats / View > Hide Archived Chats, with the setting reflected in the sidebar/search state. A project-level context menu item could also work well, e.g. Show Archived Chats in This Project, for users who only want archived history visible while inspecting one project.

    The important part for me is discoverability: archive should behave like "hide completed work from the default view", not like "move this to a recovery screen under Settings".

  5. kelesmert commented on Jun 16, 2026

    @kelesmert

    @richa65 which settings? vscodes or codex extension?

  6. 0xdevalias commented on Jun 19, 2026

    @0xdevalias

    See also:


    Summary

    Adding a concrete data point from a local investigation of archived-thread discovery.

    The short version:

    • An archived chat was findable in Settings > Archived chats.
    • The same archived chat was not findable through the normal/model-facing thread search/list surface.
    • The installed app-server schema already supports archived-aware thread/list and thread/search requests using archived: true.
    • The Desktop Settings UI appears to use that archived-aware path, while normal/sidebar/model-facing search paths appear to default to non-archived searches.

    So the practical gap appears to be:

    The underlying app-server protocol can list/search archived threads, and Settings uses that capability, but the primary search/list surfaces do not consistently expose it.

    Environment Inspected

    • Codex Desktop: 26.609.41114
    • CFBundleVersion: 3888
    • Bundle ID: com.openai.codex
    • Codex CLI: codex-cli 0.139.0
    • macOS app bundle: /Applications/Codex.app

    app.asar file SHA-256 from:

    shasum -a 256 /Applications/Codex.app/Contents/Resources/app.asar

    Result:

    586dcb004fc1dc50030bcdd10677e06fbb771c2b016f62880df16e58ff134050
    

    ElectronAsarIntegrity entry from Info.plist:

    Resources/app.asar SHA256: 3e01c3b6a7a8d792570153a7cca28b1cc6ab1271324195fb5ea4033e0ca9eef7
    

    Useful validation commands:

    codex --version
    plutil -p /Applications/Codex.app/Contents/Info.plist
    shasum -a 256 /Applications/Codex.app/Contents/Resources/app.asar

    Repro Context

    I had an archived chat that was findable in Settings > Archived chats, but not findable through the normal/model-facing thread search/list surface.

    That led me to compare:

    • the generated app-server schema;
    • the Desktop app bundle;
    • local metadata storage;
    • direct app-server calls from a shell.

    App Bundle Evidence

    To inspect the app bundle:

    mkdir -p "$TMPDIR/codex-asar"
    npx --yes @electron/asar extract /Applications/Codex.app/Contents/Resources/app.asar "$TMPDIR/codex-asar"

    Version-specific files where I found the relevant logic after extracting app.asar:

    $TMPDIR/codex-asar/webview/assets/app-server-manager-signals-Coif6OOI.js
    $TMPDIR/codex-asar/webview/assets/data-controls-D-xOtvPq.js
    $TMPDIR/codex-asar/webview/assets/app-main-fcIxOLz5.js
    $TMPDIR/codex-asar/webview/assets/sidebar-thread-list-signals-D5pCHKg3.js
    $TMPDIR/codex-asar/webview/assets/sidebar-signals-BA19kopf.js
    

    The filenames are hashed and may vary by release, so these searches are more portable than relying on exact filenames:

    rg -n 'thread/list|thread/search|archived:!1|archived:!0|list-archived-threads|Archived chats|invalidate-thread-search' "$TMPDIR/codex-asar/webview/assets"

    Bundle Observations

    In app-server-manager-signals-Coif6OOI.js:

    • normal thread listing/search paths call app-server methods with archived filtering disabled;
    • examples include thread/list with archived: false and thread/search with archived: false;
    • the same file has a separate archived path, exposed internally as something like listArchivedThreads, which calls thread/list with archived: true.

    In data-controls-D-xOtvPq.js:

    • the Settings archived-chat UI loads archived entries through the internal list-archived-threads command;
    • it then applies client-side fuzzy filtering over metadata such as title/project labels.

    In app-main-fcIxOLz5.js and sidebar-related bundles:

    • normal/global search appears to use the non-archived search path;
    • archived IDs appear to be used for some display/state handling, rather than as a general “search archived too” mode.

    App-server Schema Evidence

    The installed CLI can generate the protocol schema:

    mkdir -p "$TMPDIR/codex-schema"
    codex app-server generate-json-schema --experimental --out "$TMPDIR/codex-schema"

    Relevant generated files:

    $TMPDIR/codex-schema/v2/ThreadListParams.json
    $TMPDIR/codex-schema/v2/ThreadSearchParams.json
    

    Both schemas include an archived parameter. In the generated schema I inspected, the description was effectively:

    Optional archived filter; when set to true, only archived threads are returned. If false or null, only non-archived threads are returned.
    

    ThreadListParams also includes searchTerm, described as a substring filter for the extracted thread title. ThreadSearchParams includes searchTerm as a required full-text/substr query.

    Schema validation command:

    mkdir -p "$TMPDIR/codex-schema"
    codex app-server generate-json-schema --experimental --out "$TMPDIR/codex-schema"
    
    jq '.properties.archived, .properties.searchTerm' \
      "$TMPDIR/codex-schema/v2/ThreadListParams.json" \
      "$TMPDIR/codex-schema/v2/ThreadSearchParams.json"

    Direct App-server Calls

    I also tested calling the local app-server directly from a shell.

    Protocol shape:

    • transport: JSONL over stdio;
    • JSON-RPC-like messages, with the normal "jsonrpc": "2.0" field omitted on the wire;
    • initialize first;
    • send the initialized notification;
    • then call thread/search or thread/list with archived: true.

    The direct stdio server may need normal writable access to $CODEX_HOME for runtime bookkeeping, even for read-only queries. In a heavily sandboxed environment this can fail with SQLite/runtime permission errors, but from a normal terminal it should work.

    Example Archived Search Command

    This tries thread/search first, then falls back to title filtering via thread/list. It also prints explicit messages for app-server errors, no response, and no matches.

    QUERY='title or content fragment here'
    LIMIT="${LIMIT:-50}"
    OUT="$(mktemp)"
    trap 'rm -f "$OUT"' EXIT
    
    {
      printf '%s\n' \
        '{"id":1,"method":"initialize","params":{"clientInfo":{"name":"archived-thread-search","title":null,"version":"0.1.0"},"capabilities":{"experimentalApi":true,"requestAttestation":false,"optOutNotificationMethods":[]}}}' \
        '{"method":"initialized"}'
    
      jq -nc --arg q "$QUERY" --argjson limit "$LIMIT" \
        '{id:2,method:"thread/search",params:{searchTerm:$q,archived:true,limit:$limit,sortKey:"updated_at"}}'
    
      jq -nc --arg q "$QUERY" --argjson limit "$LIMIT" \
        '{id:3,method:"thread/list",params:{searchTerm:$q,archived:true,limit:$limit,sortKey:"updated_at"}}'
    
      # Keep stdin open briefly; immediate EOF can shut the server down before later
      # requests are processed in simple shell pipelines.
      sleep 2
    } | codex app-server --stdio > "$OUT"
    
    jq -rs --arg q "$QUERY" '
      def resp($id): map(select(type == "object" and .id == $id))[0];
      def data($id): (resp($id).result.data // []);
      def err($id): (resp($id).error // null);
    
      if (resp(2) == null and resp(3) == null) then
        "No app-server response was returned. Raw output follows:\n" +
        (map(tostring) | join("\n"))
    
      elif err(2) != null then
        "thread/search failed:\n" + (err(2) | tostring)
    
      elif (data(2) | length) > 0 then
        "Found archived matches via thread/search:\n" +
        (data(2) | map(@json) | join("\n"))
    
      elif err(3) != null then
        "thread/search returned no matches, and thread/list fallback failed:\n" +
        (err(3) | tostring)
    
      elif (data(3) | length) > 0 then
        "thread/search returned no matches; found archived title matches via thread/list:\n" +
        (data(3) | map(@json) | join("\n"))
    
      else
        "No archived thread matches for: " + $q + "\n\n" +
        "Tried:\n" +
        "- thread/search with archived:true\n" +
        "- thread/list with archived:true and searchTerm\n\n" +
        "Next local metadata fallback:\n" +
        "CODEX_HOME=\"${CODEX_HOME:-$HOME/.codex}\"\n" +
        "rg -n --fixed-strings " + ($q | @sh) + " \"$CODEX_HOME/session_index.jsonl\" \"$CODEX_HOME/archived_sessions\""
      end
    ' "$OUT"

    Daemon Proxy Variant

    If a managed app-server daemon is already running, the same JSONL can be sent through the proxy instead:

    codex app-server daemon start

    Then replace:

    } | codex app-server --stdio > "$OUT"

    with:

    } | codex app-server proxy > "$OUT"

    Local Metadata Evidence

    Without dumping private transcript contents, these locations are relevant:

    $CODEX_HOME/state_5.sqlite
    $CODEX_HOME/session_index.jsonl
    $CODEX_HOME/archived_sessions/
    $CODEX_HOME/sessions/
    

    Metadata-only inspection:

    CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
    
    sqlite3 -readonly "$CODEX_HOME/state_5.sqlite" '.schema threads'
    
    sqlite3 -readonly -header -column "$CODEX_HOME/state_5.sqlite" \
      "select archived, count(*) as count from threads group by archived;"

    Title search via the session index:

    CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
    rg -n 'some title fragment' "$CODEX_HOME/session_index.jsonl"

    Archived transcript filename search by thread ID:

    CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
    find "$CODEX_HOME/archived_sessions" -type f -name '*THREAD_ID*.jsonl'

    One caveat: in my local repro, the metadata sources were not perfectly equivalent. The session index and archived transcript location reflected the archived thread I was looking for, while one SQLite row for the same thread appeared stale. So local workarounds should avoid treating a single metadata source as authoritative.

    Practical Workarounds

    1. Built-in UI: Settings > Archived chats

    Manual, safest, and currently supported.

    Codex Desktop > Settings > Archived chats
    

    Tradeoff: reliable and privacy-preserving, but disconnected from the main sidebar/project history and not usable by automation/model-facing tools.

    2. Use app-server API with archived: true

    Best technical direction because it uses the intended protocol shape.

    Conceptual thread/search request:

    {
      "method": "thread/search",
      "params": {
        "searchTerm": "title or content fragment",
        "archived": true,
        "limit": 50
      }
    }

    Conceptual thread/list request:

    {
      "method": "thread/list",
      "params": {
        "searchTerm": "title fragment",
        "archived": true,
        "limit": 50,
        "cursor": null
      }
    }

    Tradeoff: robust and metadata-friendly, but it depends on tooling exposing the full app-server parameter surface. Some model-facing wrappers currently expose only query / limit, so they cannot pass archived: true.

    3. Search $CODEX_HOME/session_index.jsonl plus $CODEX_HOME/archived_sessions/

    Useful for local users and read-only automation.

    CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
    QUERY='title fragment here'
    
    rg -n --fixed-strings "$QUERY" "$CODEX_HOME/session_index.jsonl"

    If that gives a thread ID, check whether it has an archived transcript:

    CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
    THREAD_ID='paste-thread-id-here'
    
    find "$CODEX_HOME/archived_sessions" -type f -name "*$THREAD_ID*.jsonl"

    Tradeoff: fast and low-risk if limited to titles/IDs/paths. It may miss content-only matches and may need reconciliation across metadata files.

    4. Query $CODEX_HOME/state_5.sqlite read-only

    Good for structured metadata when it is up to date:

    CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
    QUERY='%title fragment here%'
    
    sqlite3 -readonly -header -column "$CODEX_HOME/state_5.sqlite" \
      "select id, title, archived, archived_at, cwd, rollout_path
       from threads
       where archived = 1 and title like '$QUERY'
       order by updated_at desc
       limit 50;"

    A safer parameterized version is preferable in a real script, but the above shows the shape.

    Tradeoff: structured and convenient, but in my repro one row appeared stale, so this should not be the only source of truth.

    5. Full-text search archived transcripts

    Useful only when metadata/title search is insufficient:

    CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
    QUERY='exact phrase or rare term'
    
    rg -n --fixed-strings "$QUERY" "$CODEX_HOME/archived_sessions"

    Tradeoff: most reliable for content discovery, but it searches private transcript contents. This should be explicit/opt-in and results should be summarized carefully rather than dumped wholesale.

    6. Temporarily unarchive, search normally, then rearchive

    This is a workaround but not a good one.

    Tradeoff: it mutates user state, pollutes the active sidebar/project list, and makes archive less useful as a “done but preserved” state.

    Suggested Product Behavior

    • Add an obvious main-UI archived view/filter, for example Active / Archived / All.
    • Let normal thread search include archived chats when the user selects All or enables an archived filter.
    • Mark archived results clearly with an archive badge/icon or muted styling.
    • Keep archived chats grouped under their original project when shown in project history.
    • Support opening archived chats read-only or with a clear Unarchive action, rather than requiring unarchive first.
    • Expose the same archived-aware search/list capability to model-facing tools/API wrappers, not just the Settings UI.

    Implementation Note

    This does not appear to require inventing a new storage model. The installed app-server schema already exposes archived filtering, and direct thread/search / thread/list calls can express archived-aware queries today.

    The missing piece is making archived-aware search/listing available consistently in the main UI and tool surfaces.

  7. changed the title [-]Restore archived chats access from the main Codex UI[/-] [+][S] Restore archived chats access from the main Codex UI[/+] on Jul 31, 2026
  8. changed the title [-][S] Restore archived chats access from the main Codex UI[/-] [+]🩹 Restore archived chats access from the main Codex UI[/+] on Aug 3, 2026
  9. lorivalmatias commented on Aug 3, 2026

    @lorivalmatias

    This issue also affects the Codex extension for VS Code on Windows.

    The extension provides an option to archive a conversation, but there is no visible option to browse or restore archived conversations afterward. The “Archived chats” section mentioned in the documentation is not available in the extension settings.

    I was only able to recover my conversations by installing the Codex CLI, locating the session IDs under .codex/archived_sessions, and running codex unarchive manually for each one.

    It would be very helpful to add an “Archived chats” view to the VS Code extension, with options to search, unarchive individual conversations, and unarchive all. Currently, users can easily archive a conversation without having any discoverable way to restore it through the extension.

  10. kelesmert commented on Aug 3, 2026

    @kelesmert

    @lorivalmatias i made a cli tool that finds,moves archived chats, works well with vscode codex extension, i can share if you want

  11. shelby-carter commented on Aug 13, 2026

    @shelby-carter

    I would never be able to figure out where to find archived chats if not for this ticket. What a horrible UX!

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions