Skip to content

Instantly share code, notes, and snippets.

@daniel-farina
Last active May 30, 2026 22:37
Show Gist options
  • Select an option

  • Save daniel-farina/b2397cba725fd0703fabce5e3153849f to your computer and use it in GitHub Desktop.

Select an option

Save daniel-farina/b2397cba725fd0703fabce5e3153849f to your computer and use it in GitHub Desktop.
Patching a Custom Theme into the Grok CLI (binary edit walkthrough)

Patching a Custom Theme into the Grok CLI

⚠️ This can break Grok. If you break it, you can reinstall it. This also disables auto-updates. Try at your own risk.

A reproducible, step-by-step walkthrough for recoloring the Grok Build TUI by editing the binary.

Build-specific warning. Every byte offset in this document is for grok 0.2.11, macOS arm64. Do not copy the offsets blindly — a different version puts the colors somewhere else. Step 4 shows how to find them on your build; trust that over the literals here.

Safety. Work on a copy, never the original. Disable auto-update. Keep the rollback (Step 9) handy.

Prereqs: macOS (arm64), python3, and the Xcode command-line tools (codesign).


1. Locate the binary and the launcher

ls -l ~/.grok/bin/grok                 # this is a symlink
readlink ~/.grok/bin/grok              # -> ../downloads/grok-<version>-macos-aarch64
ls -l ~/.grok/downloads/               # the real binaries live here

Set a variable for the real file you'll be working from:

cd ~/.grok/downloads
SRC=grok-0.2.11-macos-aarch64          # adjust to your version
file "$SRC"                            # Mach-O 64-bit executable arm64
codesign -dv "$SRC" 2>&1 | grep -E "flags|TeamIdentifier"

You'll see flags=0x10000(runtime) (hardened runtime) and a Team ID — confirming you'll need to re-sign after editing.


2. Disable auto-update (so it can't clobber your work)

Edit ~/.grok/config.toml:

[cli]
auto_update = false

3. Work on a copy (never the original)

cd ~/.grok/downloads
cp -p grok-0.2.11-macos-aarch64 grok-0.2.11-neon

All patches below target grok-0.2.11-neon.


4. Find the theme color tables

Colors are stored the way the ratatui library encodes them: an RGB color is 4 bytes0x11 (the Rgb enum tag), then R, G, B. A theme is ~36 of these in a row.

Find a theme by searching for a color you already know. TokyoNight's background is #1a1b26:

python3 - <<'PY'
data = open("grok-0.2.11-macos-aarch64","rb").read()
i = data.find(bytes([0x1a,0x1b,0x26]))
print(hex(i), data[i-1:i+4].hex())     # byte before should be 0x11
PY

Then decode the surrounding region to map every built-in theme:

python3 - <<'PY'
data = open("grok-0.2.11-macos-aarch64","rb").read()
lo, hi = 0x4c0ae00, 0x4c0b300           # adjust around your hit from above
for off in range(lo, hi, 4):
    t,r,g,b = data[off],data[off+1],data[off+2],data[off+3]
    tag = f"#{r:02x}{g:02x}{b:02x}" if t==0x11 else f"[{t:02x}{r:02x}{g:02x}{b:02x}]"
    print(f"0x{off:x}: {tag}")
PY

Identify each theme by its signature color, and note the start/end offsets of the one you use:

Theme Tell-tale This build
OscuraMidnight #030304 bg ~0x4c0af70
RosePineMoon #232136 ~0x4c0b040
TokyoNight #1a1b26 ~0x4c0b120
GrokDay (light) #f5f5f5 ~0x4c0b1c0
GrokNight (dark, default) #0a0a0a bg + magenta #bb9af7 0x4c0b2500x4c0b2dc

5. (Optional) Sanity patch: one accent

Prove the pipeline with the smallest edit — turn GrokNight's magenta accent green, scoped to its range only:

python3 - <<'PY'
fn="grok-0.2.11-neon"
d=bytearray(open(fn,"rb").read())
LO,HI=0x4c0b250,0x4c0b2e0
GREEN=bytes([0x39,0xff,0x14])
i=LO
while (i:=d.find(bytes([0x11,0xbb,0x9a,0xf7]),i))!=-1 and i<HI:
    d[i+1:i+4]=GREEN; i+=4
open(fn,"wb").write(d)
print("accent patched")
PY

6. Full Matrix patch: recolor the whole theme by brightness

Map every color to a green of equal luminance (keeps contrast / readability):

python3 - <<'PY'
orig=open("grok-0.2.11-macos-aarch64","rb").read()
neon=bytearray(open("grok-0.2.11-neon","rb").read())

def matrix(r,g,b):
    luma=0.299*r+0.587*g+0.114*b
    if luma<28: return (0,max(0,round(luma*0.7)),0)      # bg -> near-black green
    return (0,min(255,round(40+luma*1.05)),0)            # text/accent -> bright green

def recolor(lo,hi):
    n=0
    for off in range(lo,hi,4):
        if orig[off]!=0x11: continue                     # skip non-color / None gaps
        r,g,b=orig[off+1],orig[off+2],orig[off+3]
        neon[off+1],neon[off+2],neon[off+3]=matrix(r,g,b); n+=1
    return n

main = recolor(0x4c0b250, 0x4c0b2dc+4)                   # GrokNight main palette
md   = recolor(0x4c09d60, 0x4c09dcc)                     # GrokNight markdown/syntax palette
open("grok-0.2.11-neon","wb").write(neon)
print(f"recolored {main} main + {md} markdown colors")
PY

Why two ranges? The main theme colors the chrome/accents. Assistant message text renders as markdown, which uses a separate Option<Color> palette (00000000 = None gaps between colors) located elsewhere — ~0x4c09d60 on this build, containing the body-text white #e1e1e1. Recolor both or the replies stay white.


7. Re-sign (the edit broke the signature)

cd ~/.grok/downloads
codesign -f -s - grok-0.2.11-neon      # ad-hoc re-sign
codesign -v grok-0.2.11-neon && echo "sig OK"
./grok-0.2.11-neon version             # must print a version => it runs

8. Activate it

cd ~/.grok/bin
ln -sf ../downloads/grok-0.2.11-neon grok
grok version                           # confirm symlink resolves

Restart fully. Grok keeps a persistent leader process holding the old binary in memory — quit every session (and kill any lingering grok leader) before relaunching, or you won't see the change.


9. Rollback (instant)

ln -sf ../downloads/grok-0.2.11-macos-aarch64 ~/.grok/bin/grok
# optional: re-enable auto_update in ~/.grok/config.toml

Tuning notes

  • Brighter/pure phosphor: raise the floor in matrix() (e.g. round(60+luma*1.0)) or clamp the brightest tier toward #00FF41.
  • Different hue: keep the luminance idea, just steer the output channels (amber = high R+G, ice = high G+B).
  • Other themes: repeat Step 4–6 against that theme's offset range; ranges are independent.
  • After a version bump: re-run Step 4 — offsets will have moved. Nothing else changes.

Caveats

  • Unofficial, unsupported, breaks on every update.
  • Offsets are build-specific (0.2.11 arm64 here).
  • Ad-hoc re-signing is for running it yourself, not distribution.
  • Don't ship a patched binary to anyone else.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment