App auto scroll is buggy / broken

Resolved 💬 16 comments Opened Feb 18, 2026 by BlueBlazin Closed Feb 25, 2026
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using (From “About Codex” dialog)?

26.217.1959 (669)

What subscription do you have?

Pro

What platform is your computer?

Darwin 25.2.0 arm64 arm

What issue are you seeing?

Since this update (version 26.217.1959 (669)) autoscroll in the desktop app is super buggy and not working when Codex app is not focused / in foreground.

Edit: it seems sometimes it doesn't auto scroll even when the app window is focused and in the foreground.

What steps can reproduce the bug?

Get the down arrow to appear. Click it to cause the UI to scroll to the bottom. Move the Codex app window to the background (just focus on another window).

What is the expected behavior?

Auto scroll should not stop.

Additional information

_No response_

View original on GitHub ↗

16 Comments

github-actions[bot] contributor · 5 months ago

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

  • #10735
  • #4196
  • #6404

Powered by Codex Action

dev-minsoo · 5 months ago

I’m seeing the same overall symptom, but in my case it is not intermittent.

Behavior in my environment:

  • Auto-scroll works normally when I’m at the bottom.
  • If I click the down-arrow and stay at the bottom, auto-scroll keeps working.
  • Once I manually scroll up so the down-arrow is visible, auto-scroll stops following new output.
  • In that state, sending a new message does not bring the view back to the latest output.

Repro steps:

  1. Open a long thread.
  2. Scroll up until the down-arrow appears.
  3. Send a new message without clicking the down-arrow.
  4. Observe the viewport stays at the current position instead of following the latest output.

Environment: Codex 26.217.1959 (669), Pro, Darwin 25.3.0 arm64

jonlave · 5 months ago

This started happening to me after the latest update yesterday (2/17/2026 - version 26.217.1959 (669)). It is very annoying that I have to keep clicking the "scroll to end" arrow at the bottom-center of the execution/thinking pane. It was fine before.

zyuapp · 5 months ago

Noticing the same issue here as well. Installed the app today.

samdeane · 5 months ago

+1 on this. I don't think it ever auto-scrolls for me now, regardless of focus.

saintflow47 · 5 months ago

can confirm!

BlueBlazin · 4 months ago

Still not fixed and now we have to wait till at least next week :(

johanbaath · 4 months ago

This is super annoying, the scroll doesn't "snap" and continue to scroll so I'm doing all the heavy lifting myself

odgey · 4 months ago

This has been driving me nuts today used to work so well

jasonkuhrt · 4 months ago
Codex came up with this comedic plea for me: "At this point I’m not asking for autoscroll, I’m asking for worker’s comp for my scroll finger. Switching threads keeps dropping me in the middle, and with ~20 sessions open, my trackpad and I are in active negotiations. Codex please yeet me to the bottom on switch." yes, mfingers are hurting.

Update: safer workaround script (replacing my earlier broken one)

My previous script had a bad footgun: it wrote app.asar.backup-* inside /Applications/Codex.app/..., which can invalidate the signed app bundle and stop Codex from launching.

This revision stores backups outside the app bundle and avoids the crash-prone scroll-event loop.

  • Status: codex-scrollfix status
  • Apply: codex-scrollfix apply
  • Undo: codex-scrollfix undo
  • Migrate old in-bundle backups: codex-scrollfix migrate-backups
#!/usr/bin/env bash
set -euo pipefail

APP="${CODEX_APP_PATH:-/Applications/Codex.app}"
ASAR="$APP/Contents/Resources/app.asar"
BACKUP_DIR="${CODEX_SCROLLFIX_BACKUP_DIR:-$HOME/.local/share/codex-scrollfix/backups}"
MODE="${1:-apply}"

if [[ ! -f "$ASAR" ]]; then
  echo "error: Codex app bundle not found at $ASAR" >&2
  exit 1
fi

if ! command -v npx >/dev/null 2>&1; then
  echo "error: npx is required" >&2
  exit 1
fi

mkdir -p "$BACKUP_DIR"

find_latest_backup() {
  local files
  shopt -s nullglob
  files=("$BACKUP_DIR"/app.asar.backup-* "$ASAR".backup-*)
  shopt -u nullglob

  if (( ${#files[@]} == 0 )); then
    return 0
  fi

  ls -1t "${files[@]}" 2>/dev/null | head -n1 || true
}

move_legacy_backups_out_of_bundle() {
  local legacy
  shopt -s nullglob
  legacy=("$ASAR".backup-*)
  shopt -u nullglob

  if (( ${#legacy[@]} == 0 )); then
    return 0
  fi

  local f base dest
  for f in "${legacy[@]}"; do
    base="$(basename "$f")"
    dest="$BACKUP_DIR/$base"
    if [[ -e "$dest" ]]; then
      dest="$BACKUP_DIR/$base.$(date +%s)"
    fi
    mv "$f" "$dest"
    echo "codex-scrollfix: moved legacy in-bundle backup to $dest"
  done
}

JS_TMP=""
JS_FILE=""

with_extracted_js() {
  local tmp
  tmp="$(mktemp -d -t codex-scrollfix.XXXXXX)"
  # shellcheck disable=SC2064
  trap "rm -rf '$tmp'" RETURN

  npx --yes @electron/asar extract "$ASAR" "$tmp/app" >/dev/null

  local js
  js="$(ls "$tmp"/app/webview/assets/index-*.js 2>/dev/null | head -n1 || true)"
  if [[ -z "$js" ]]; then
    echo "error: could not find webview index bundle in app.asar" >&2
    return 1
  fi

  JS_TMP="$tmp"
  JS_FILE="$js"
  "$@"
}

patch_js_file() {
  local js="$1"
  node - "$js" <<'NODE'
const fs = require('fs');
const jsPath = process.argv[2];
let src = fs.readFileSync(jsPath, 'utf8');

const original = 'e[2]!==p?(N=()=>{p&&p.scrollTo({behavior:"auto",top:p.scrollHeight})},e[2]=p,e[3]=N):N=e[3];';
const replacement = 'e[2]!==p?(N=()=>{if(!p)return;const Q=()=>{p.scrollTo({behavior:"auto",top:p.scrollHeight})};Q();if(typeof window>"u")return;window.requestAnimationFrame(Q)},e[2]=p,e[3]=N):N=e[3];';
const legacyMarker = 'p.dispatchEvent(new Event("scroll"))';

if (src.includes(replacement) || src.includes(legacyMarker)) {
  console.log('already_patched');
  process.exit(0);
}

if (!src.includes(original)) {
  console.log('anchor_not_found');
  process.exit(2);
}

src = src.replace(original, replacement);
fs.writeFileSync(jsPath, src);
console.log('patched');
NODE
}

status_impl() {
  local result
  result="$(patch_js_file "$JS_FILE" 2>/dev/null || true)"
  case "$result" in
    already_patched)
      echo "patched"
      ;;
    patched)
      echo "unpatched"
      ;;
    anchor_not_found)
      echo "unknown_build"
      ;;
    *)
      echo "unknown"
      ;;
  esac
}

apply_impl() {
  local result
  result="$(patch_js_file "$JS_FILE")"

  case "$result" in
    already_patched)
      echo "codex-scrollfix: already patched"
      return 0
      ;;
    patched)
      ;;
    anchor_not_found)
      echo "codex-scrollfix: patch anchor not found (Codex build changed)." >&2
      return 2
      ;;
    *)
      echo "codex-scrollfix: unexpected patch state: $result" >&2
      return 3
      ;;
  esac

  local stamp backup
  stamp="$(date +%Y%m%d-%H%M%S)"
  backup="$BACKUP_DIR/app.asar.backup-$stamp"
  cp "$ASAR" "$backup"

  npx --yes @electron/asar pack "$JS_TMP/app" "$JS_TMP/app.patched.asar" >/dev/null
  cp "$JS_TMP/app.patched.asar" "$ASAR"

  echo "codex-scrollfix: patch applied"
  echo "backup: $backup"
}

cmd_status() {
  with_extracted_js status_impl
}

cmd_apply() {
  with_extracted_js apply_impl
}

cmd_undo() {
  local backup="${2:-}"
  if [[ -z "$backup" ]]; then
    backup="$(find_latest_backup)"
  fi

  if [[ -z "$backup" || ! -f "$backup" ]]; then
    echo "error: no backup found. pass a backup path explicitly." >&2
    exit 1
  fi

  cp "$backup" "$ASAR"
  move_legacy_backups_out_of_bundle
  echo "codex-scrollfix: restored backup"
  echo "restored_from: $backup"
}

cmd_migrate_backups() {
  move_legacy_backups_out_of_bundle
}

case "$MODE" in
  apply)
    cmd_apply
    ;;
  status)
    cmd_status
    ;;
  undo)
    cmd_undo "$@"
    ;;
  migrate|migrate-backups)
    cmd_migrate_backups
    ;;
  *)
    echo "usage: codex-scrollfix [apply|status|undo [backup_path]|migrate-backups]" >&2
    exit 1
    ;;
esac

If Codex won’t launch after any patching experiment:

codex-scrollfix undo
# if still broken, reinstall Codex cleanly

Still hoping for an official fix so none of us need this.

garyamorris · 4 months ago

I support this issue. Very annoying

Jey123456 · 4 months ago

this issue has been driving me insane. I have a "fix" thats definitly ugly and 100% vibecoded as i didnt check whatsoever what change it actually did xD.

but codex with gpt 5.3 and this prompt
"
Fix Codex chat bottom-scroll drift in VS Code by patching the extension webview script (not minified bundle internals). Find the installed openai.chatgpt-* extension folder,

Requirements:
1) Add sticky-bottom logic:

  • Track the active transcript scroll container (search under #root, fallback to document.scrollingElement).
  • Define near-bottom threshold (~24px).
  • Set stickToBottom=true only when user is near bottom.
  • On content mutation/resize, if stickToBottom is true, force scroll to bottom multiple times (immediate + delayed retries, e.g. 20/70/160ms, plus RAF) to survive markdown/decode reflow.
  • If user scrolls up, do not force jump back down.

3) Re-scan/rebind the tracked container periodically (about 1.2s) in case the DOM node changes.
4) Ensure boot() calls both hotspot setup and autoscroll-fix setup.
5) Make minimal targeted edits and show a short diff summary.

Success criteria: when chat is already at bottom, streaming output / command completion / markdown transforms no longer drift the view upward; manual scroll-up still disables auto-stick.
"
was enough to fix its autoscroll for my usecases

gpeal contributor · 4 months ago

Could you try again on the release from today? It should be much better now.

BlueBlazin · 4 months ago

Seems to be fixed now.

saintflow47 · 4 months ago

bug is still present for the vs code extension (that pre-release version doesnt seem to be updated yet?)

CarlasHub · 13 days ago

this bug is back since last update July 7th 2026 shocking UI