Skip to content

Instantly share code, notes, and snippets.

@andrewleech
Last active February 24, 2026 11:43
Show Gist options
  • Select an option

  • Save andrewleech/43688422c58510e01818c5fc04e26b28 to your computer and use it in GitHub Desktop.

Select an option

Save andrewleech/43688422c58510e01818c5fc04e26b28 to your computer and use it in GitHub Desktop.
Fix Claude Code statusline layout (issue #27305) — single-file installer
#!/bin/bash
# Installer for claude-statusfix — fixes Claude Code statusline layout.
# https://github.com/anthropics/claude-code/issues/27305
#
# Usage: curl -fsSL https://gist.githubusercontent.com/andrewleech/43688422c58510e01818c5fc04e26b28/raw/install.sh | bash
#
# Installs claude-statusfix to ~/.local/bin/ and prints alias instructions.
set -euo pipefail
INSTALL_DIR="$HOME/.local/bin"
INSTALL_PATH="$INSTALL_DIR/claude-statusfix"
# --- Write the script --------------------------------------------------------
mkdir -p "$INSTALL_DIR"
cat > "$INSTALL_PATH" << 'SCRIPT'
#!/bin/bash
# Claude CLI wrapper that patches the footer flex layout so the statusline
# renders on its own row, while hints and notifications share a second row.
# See: https://github.com/anthropics/claude-code/issues/27305
#
# The patch is applied idempotently to cli.js on each launch, so Claude
# Code updates are automatically re-patched on next run.
set -euo pipefail
# --- Patch definitions -------------------------------------------------------
PATCH1_ORIG='e=t$.createElement(I,{flexDirection:"column",flexShrink:0},D1,a)'
PATCH1_NEW='e=t$.createElement(I,{flexShrink:0},D1)'
PATCH2_ORIG='H1=t$.createElement(I,{flexDirection:"row",justifyContent:"space-between",paddingX:2,gap:1},e,j1)'
PATCH2_NEW='H1=t$.createElement(I,{flexDirection:"column",paddingX:2},e,t$.createElement(I,{flexDirection:"row",justifyContent:"space-between",gap:1},t$.createElement(I,{flexShrink:1,height:1,overflowY:"hidden"},a),j1))'
PATCH3_ORIG='flexDirection:"column",alignItems:"flex-end",flexShrink:1,overflowX:"hidden"'
PATCH3_NEW='flexDirection:"column",alignItems:"flex-end",flexShrink:0,overflowX:"hidden"'
# --- Locate cli.js -----------------------------------------------------------
find_claude_cli() {
local claude_cmd
claude_cmd=$(command -v claude 2>/dev/null) || true
if [ -n "$claude_cmd" ] && [ -f "$claude_cmd" ]; then
local resolved self_path
resolved=$(readlink -f "$claude_cmd" 2>/dev/null) || resolved=""
self_path=$(readlink -f "$0" 2>/dev/null) || self_path=""
if [ -n "$resolved" ] && [ -f "$resolved" ] && [ "$resolved" != "$self_path" ]; then
echo "$resolved"; return 0
fi
if [ "$claude_cmd" != "$self_path" ]; then
echo "$claude_cmd"; return 0
fi
fi
if command -v npm >/dev/null 2>&1; then
local npm_cli
npm_cli="$(npm root -g 2>/dev/null)/@anthropic-ai/claude-code/cli.js"
if [ -f "$npm_cli" ]; then echo "$npm_cli"; return 0; fi
fi
if [ -d "$HOME/.nvm" ]; then
local nvm_cli
nvm_cli=$(find "$HOME/.nvm/versions/node" \
-path "*/node_modules/@anthropic-ai/claude-code/cli.js" \
2>/dev/null | head -1)
if [ -f "$nvm_cli" ]; then echo "$nvm_cli"; return 0; fi
fi
local p
for p in \
"/usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js" \
"/usr/lib/node_modules/@anthropic-ai/claude-code/cli.js"; do
if [ -f "$p" ]; then echo "$p"; return 0; fi
done
return 1
}
if [ -n "${CLAUDE_CLI:-}" ] && [ -f "$CLAUDE_CLI" ]; then
: # user override
else
CLAUDE_CLI=$(find_claude_cli) || true
if [ -z "$CLAUDE_CLI" ] || [ ! -f "$CLAUDE_CLI" ]; then
echo "Error: Could not locate Claude CLI (cli.js)" >&2
echo "Set CLAUDE_CLI=/path/to/cli.js to override." >&2
exit 1
fi
fi
# --- Apply patches idempotently ----------------------------------------------
apply_patches() {
local file="$1"
local backup="${file}.bak"
if grep -qF "$PATCH1_NEW" "$file" 2>/dev/null &&
grep -qF "$PATCH2_NEW" "$file" 2>/dev/null &&
grep -qF "$PATCH3_NEW" "$file" 2>/dev/null; then
return 0
fi
if [ -f "$backup" ]; then
if grep -qF "$PATCH2_ORIG" "$backup" 2>/dev/null; then
cp "$backup" "$file"
fi
fi
local missing=0
if ! grep -qF "$PATCH1_ORIG" "$file" 2>/dev/null; then
if ! grep -qF "$PATCH1_NEW" "$file" 2>/dev/null; then
echo "[statusfix] Warning: pattern 1 (e element) not found in cli.js." >&2
missing=1
fi
fi
if ! grep -qF "$PATCH2_ORIG" "$file" 2>/dev/null; then
if ! grep -qF "$PATCH2_NEW" "$file" 2>/dev/null; then
echo "[statusfix] Warning: pattern 2 (H1 footer) not found in cli.js." >&2
missing=1
fi
fi
if ! grep -qF "$PATCH3_ORIG" "$file" 2>/dev/null; then
if ! grep -qF "$PATCH3_NEW" "$file" 2>/dev/null; then
echo "[statusfix] Warning: pattern 3 (G0q notif) not found in cli.js." >&2
missing=1
fi
fi
if [ "$missing" -eq 1 ]; then
echo "[statusfix] Claude Code version may have changed; patch skipped." >&2
return 0
fi
if [ ! -f "$backup" ]; then
cp "$file" "$backup"
fi
python3 -c "
import sys
with open(sys.argv[1], 'r') as f:
c = f.read()
pairs = [(sys.argv[i], sys.argv[i+1]) for i in range(2, len(sys.argv), 2)]
applied = 0
for old, new in pairs:
if old in c:
c = c.replace(old, new, 1)
applied += 1
with open(sys.argv[1], 'w') as f:
f.write(c)
print(f'[statusfix] Applied {applied}/3 replacements to {sys.argv[1]}', file=sys.stderr)
" "$file" \
"$PATCH1_ORIG" "$PATCH1_NEW" \
"$PATCH2_ORIG" "$PATCH2_NEW" \
"$PATCH3_ORIG" "$PATCH3_NEW"
}
apply_patches "$CLAUDE_CLI"
# --- Launch ------------------------------------------------------------------
exec node "$CLAUDE_CLI" "$@"
SCRIPT
chmod +x "$INSTALL_PATH"
# --- Verify ------------------------------------------------------------------
echo "Installed claude-statusfix to $INSTALL_PATH"
echo ""
# Check if ~/.local/bin is on PATH
if ! echo "$PATH" | tr ':' '\n' | grep -qx "$INSTALL_DIR"; then
echo "Note: $INSTALL_DIR is not on your PATH."
echo "You may need to add it first (most distros source ~/.profile on login)."
echo ""
fi
echo "To launch Claude with the statusline fix, run:"
echo " claude-statusfix"
echo ""
echo "To make it the default, add an alias to your shell rc:"
echo ""
echo " echo 'alias claude=\"claude-statusfix\"' >> ~/.bashrc"
echo ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment