Configurable session limit for /resume picker

Status Closed — not planned
Maintainer reply None cached
Activity 6 comments · opened Apr 15, 2026 · closed May 28, 2026

Problem

The /resume picker is hardcoded to display only the 50 most recent sessions. Power users accumulate hundreds of sessions (I have 488 .jsonl files across projects) and cannot access older conversations through the picker UI.

Prior issues

This has been requested multiple times, with all issues closed as duplicate or stale without resolution:

  • #35698, #29052, #24777, #24435, #25130, #25729, #23375, #23072, #23933

The limit was previously raised from ~10 to 50, but there's still no way to configure it or paginate beyond it.

Proposed solution

One or more of:

  • A configurable resumeLimit setting in settings.json
  • Pagination / "load more" in the picker that actually works beyond the initial batch
  • A --resume-limit N CLI flag

Workaround

Users can bypass the picker with claude --resume <session-id>, but discovering the session ID requires manually browsing .jsonl files on disk.

View original on GitHub ↗

6 Comments

github-actions[bot] · 6 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/35698
  2. https://github.com/anthropics/claude-code/issues/29052
  3. https://github.com/anthropics/claude-code/issues/24777

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

alexboden · 6 months ago

All three linked "duplicates" are themselves closed (as duplicates or stale), with no open canonical issue tracking this feature:

  • #35698 → closed as duplicate of #29052
  • #29052 → closed as duplicate of #24777
  • #24777 → closed as duplicate of #24435 (also closed/stale)

There is no open issue for this request to consolidate into. Please keep this one open or reopen one of the earlier issues as the canonical tracker.

gnutix · 5 months ago

Same issue here with 155+ sessions. Since this hasn't been addressed across the many dupes, Claude wrote a byte-level binary patch that uncaps the initial load. Sharing in case it helps others.

The cap: /resume's initial-load callback calls the loader functions (r68() / $f$($) in 2.1.116) with no count argument, falling back to default parameters that reference a module-level constant — var t68=50. The identifier is renamed by the minifier each version (LH8 in 2.1.112, j$8 in 2.1.114, t68 in 2.1.116), but the structure is stable.

The patch: In the native binary (~/.local/share/claude/versions/<version>), replace every use of that identifier:

  • ??<var>) → ??1e9) (the Uw6 fallback)
  • =<var>){ → =1e9){ (three default-parameter sites in the loader functions)

1e9 is byte-length-compatible with a 3-char identifier, so no offsets shift. The bundled binary has two duplicate code blocks (at ~118M and ~233M), both get patched.

Script (with anchor-based discovery via the /resume: loading sessions for cwd= log string, so it survives minifier renames across versions):

#!/usr/bin/env python3
"""Patch Claude Code's /resume picker to uncap the initial session load."""
from __future__ import annotations
import os
import re
import shutil
import sys
import tempfile
from pathlib import Path

VERSIONS_DIR = Path.home() / ".local/share/claude/versions"
BACKUP_DIR = Path.home() / ".claude/scripts/backups"
ANCHOR = b"/resume: loading sessions for cwd="
REPLACEMENT_LITERAL = b"1e9"
assert len(REPLACEMENT_LITERAL) == 3


def log(msg):
    print(f"[patch-picker-limit] {msg}", file=sys.stderr)


def discover_cap_var(data):
    anchor_idx = data.find(ANCHOR)
    if anchor_idx < 0:
        return None
    window = data[max(0, anchor_idx - 5000):anchor_idx]
    match = re.search(rb"[=?]{1,2}([A-Za-z_\$][A-Za-z0-9_\$]{2})\)", window)
    return match.group(1) if match else None


def patch_binary(path):
    data = path.read_bytes()
    var_name = discover_cap_var(data)
    if var_name is None:
        return "SKIP: loader anchor not found"
    if var_name == REPLACEMENT_LITERAL:
        return "already patched"
    if len(var_name) != 3:
        return f"SKIP: identifier '{var_name.decode()}' is {len(var_name)} bytes, not 3"

    new_data = data
    total = 0
    for prefix in (b"??", b"="):
        old = prefix + var_name + b")"
        count = new_data.count(old)
        if count:
            new_data = new_data.replace(old, prefix + REPLACEMENT_LITERAL + b")")
            total += count
    if total == 0 or len(new_data) != len(data):
        return "SKIP: no patch applied"

    BACKUP_DIR.mkdir(parents=True, exist_ok=True)
    backup_path = BACKUP_DIR / f"{path.name}.orig"
    if not backup_path.exists():
        shutil.copy2(path, backup_path)

    # Atomic write preserves the inode so running claude processes are unaffected.
    fd, tmp_path = tempfile.mkstemp(dir=path.parent, prefix=f".{path.name}.", suffix=".tmp")
    try:
        with os.fdopen(fd, "wb") as fh:
            fh.write(new_data)
        os.chmod(tmp_path, path.stat().st_mode)
        os.replace(tmp_path, path)
    except Exception:
        if os.path.exists(tmp_path):
            os.unlink(tmp_path)
        raise

    return f"patched ({total} replacements, var={var_name.decode()})"


def main():
    if not VERSIONS_DIR.is_dir():
        log(f"versions dir not found: {VERSIONS_DIR}")
        return 0
    any_action = False
    for binary in sorted(VERSIONS_DIR.iterdir()):
        if not binary.is_file():
            continue
        try:
            status = patch_binary(binary)
        except Exception as exc:
            log(f"{binary.name}: ERROR {exc}")
            continue
        if status != "already patched":
            log(f"{binary.name}: {status}")
            any_action = True
    if not any_action:
        log("all binaries already patched")
    return 0


if __name__ == "__main__":
    sys.exit(main())

Save as ~/.claude/scripts/patch-picker-limit.py, chmod +x, and wire as a SessionStart hook in ~/.claude/settings.json so auto-updates get patched one session after they land:

"SessionStart": [
  {
    "matcher": "",
    "hooks": [
      {
        "type": "command",
        "command": "python3 /home/YOU/.claude/scripts/patch-picker-limit.py",
        "timeout": 30,
        "async": true
      }
    ]
  }
]

Atomic writes via os.replace() so running claude processes aren't disturbed; backups of each original version land in ~/.claude/scripts/backups/.

A resumeLimit setting in settings.json would still be the right fix — +1 from me.

github-actions[bot] · 4 months ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

otternetwork · 3 months ago

Reopening request — this issue was auto-closed by a stale bot without developer review.

This has become more urgent with v2.1.113, which switched from node.exe cli.js to a compiled SEA binary (claude.exe). The JS source files are no longer shipped, so the workaround of patching the hardcoded =50 limit in the minified bundle is no longer possible.

Reframed ask: Please expose a configurable session limit for /resume via settings.json, e.g.:

{
  "resume": {
    "maxSessions": 200
  }
}

The default can stay at 50. This is a one-line change — the limit is already a default parameter in the session-loading functions. Making it configurable would let power users with many sessions adjust it without patching internals (which is no longer feasible post-SEA).

github-actions[bot] · 1 month ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.