Skip to content

Instantly share code, notes, and snippets.

@dfevre
Last active May 22, 2026 13:28
Show Gist options
  • Select an option

  • Save dfevre/250bc8bc28149a2c125b35434347f235 to your computer and use it in GitHub Desktop.

Select an option

Save dfevre/250bc8bc28149a2c125b35434347f235 to your computer and use it in GitHub Desktop.
GitHub Copilot CLI custom statusline — Tokyo Moon colours, Nerd Fonts, git status, session name, model + context usage
#!/bin/bash
# GitHub Copilot CLI — Custom Statusline
#
# A Tokyo Moon-themed powerline statusline for GitHub Copilot CLI.
#
# Layout:
# [cwd] > [branch +x !x ?x] session name ····· +lines -lines [model [ctx%]]
#
# Dependencies:
# - Nerd Fonts (https://www.nerdfonts.com/) — required for powerline glyphs and icons
# - Tokyo Moon colour palette — colours are hardcoded to match the theme
#
# Setup:
# 1. Save this file to ~/.copilot/statusline.sh
# 2. chmod +x ~/.copilot/statusline.sh
# 3. Add to ~/.copilot/settings.json:
#
# "statusLine": {
# "type": "command",
# "command": "~/.copilot/statusline.sh"
# }
#
input=$(cat)
COLUMNS=$(stty size < /dev/tty 2>/dev/null | awk '{print $2}')
echo "$input" | COLUMNS="$COLUMNS" python3 -c "
import sys, json, subprocess, os, re, shutil
d = json.load(sys.stdin)
name = d.get('session_name', '')
cwd = d.get('cwd', os.getcwd())
# Tokyo Moon colours
blue_bg = '48;2;130;170;255'
blue_fg = '38;2;130;170;255'
dark_bg = '48;2;59;66;97'
dark_fg = '38;2;59;66;97'
text_dark = '38;2;30;32;48'
text_light = '38;2;200;211;245'
def strip_ansi(s):
return re.sub(r'\033\[[^m]*m', '', s)
def visible_len(s):
return len(re.sub(r'[\uE000-\uF8FF]', ' ', strip_ansi(s)))
# Git info
git_info = None
try:
branch = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], cwd=cwd, stderr=subprocess.DEVNULL).decode().strip()
git_info = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'], cwd=cwd, stderr=subprocess.DEVNULL).decode().strip() if branch == 'HEAD' else branch
ls = subprocess.check_output(['git', 'status', '--porcelain'], cwd=cwd, stderr=subprocess.DEVNULL).decode().splitlines()
staged_count = sum(1 for l in ls if len(l) > 0 and l[0] in 'MADRC')
modified_count = sum(1 for l in ls if len(l) > 1 and l[1] in 'MD')
untracked_count = sum(1 for l in ls if l.startswith('??'))
ind = ''
if staged_count: ind += f' \u271a{staged_count}'
if modified_count: ind += f' !{modified_count}'
if untracked_count: ind += f' ?{untracked_count}'
try:
ahead, behind = subprocess.check_output(
['git', 'rev-list', '--count', '--left-right', '@{upstream}...HEAD'],
cwd=cwd, stderr=subprocess.DEVNULL
).decode().split()
if int(behind): ind += f' \u2191{behind}'
if int(ahead): ind += f' \u2193{ahead}'
except Exception:
pass
git_info += ind
except Exception:
pass
home = os.path.expanduser('~')
display_cwd = cwd.replace(home, '~') if cwd.startswith(home) else cwd
model = d.get('model', {}).get('display_name', '')
ctx_used = d.get('context_window', {}).get('current_context_used_percentage', '')
model_label = f'{model} [{ctx_used}%]' if model and ctx_used != '' else model
term_width = int(os.environ.get('COLUMNS', 0)) or shutil.get_terminal_size((80, 24)).columns
try:
import fcntl, termios, struct
for fd in (0, 1, 2):
try:
hw = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, b' '))
if hw[1] > 0:
term_width = hw[1]
break
except Exception:
pass
except Exception:
pass
# Left: [blue: cwd] -> [dark: git] -> [session name, no bg]
left = f'\033[{blue_bg}m\033[{text_dark}m \uF07C {display_cwd} '
if git_info:
left += f'\033[{dark_bg}m\033[{blue_fg}m\uE0B0\033[{blue_fg}m \uE0A0 {git_info} \033[0m\033[{dark_fg}m\uE0B0'
else:
left += f'\033[{dark_bg}m\033[{blue_fg}m\uE0B0\033[0m\033[{dark_fg}m\uE0B0'
if name:
left += f'\033[0m\033[{text_light}m \uF02B {name} '
lines_added = d.get('cost', {}).get('total_lines_added', 0)
lines_removed = d.get('cost', {}).get('total_lines_removed', 0)
lines_text = f' +{lines_added} -{lines_removed} ' if (lines_added or lines_removed) else ''
# Right: [dark: lines +/-] [blue: model [ctx%]]
model_text = f' \uF135 {model_label} ' if model_label else ''
lines_seg = f'\033[{dark_fg}m\uE0B2\033[{dark_bg}m\033[{blue_fg}m{lines_text}' if lines_text else ''
model_seg = f'\033[{blue_fg}m\uE0B2\033[{blue_bg}m\033[{text_dark}m{model_text}\033[0m' if model_text else ''
right = lines_seg + model_seg
right_len = (visible_len(lines_text) + 1 if lines_text else 0) + (visible_len(model_text) + 1 if model_text else 0)
left_len = visible_len(left)
padding = max(0, term_width - left_len - right_len)
print(left + ' ' * padding + right)
"
@dfevre

dfevre commented May 22, 2026

Copy link
Copy Markdown
Author

Looks like this -

image

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