Troubleshooting

Nerd Fonts over mobile SSH: why your prompt is full of boxes (2026)

The tofu boxes in your phone's SSH session are a font problem, not an SSH problem: Nerd Font icons live in Unicode's Private Use Area, and a mobile client can only draw them if the exact font it renders with contains them. Termius shipped Nerd Font v3 glyphs on mobile in June 2026, Blink Shell and Prompt can load your own patched font, and ConnectBot still can't change fonts at all — but the fix that works on every client is to make the prompt itself glyph-optional.

CC Chen Chen· Founder·2026-08-24·11 min read

The short answer

The boxes are a font problem on the phone, not an SSH problem, and not a server problem. Nerd Font icons — the Powerline arrows in a Powerlevel10k prompt, the Git branch mark, the little language logos in lsd output — live in Unicode’s Private Use Area, a region with no assigned meaning. Only a font that was deliberately patched with those glyphs can draw them, and the font that decides what you see is the one your mobile SSH client renders with. Installing a Nerd Font on the server accomplishes nothing at all: the server transmits codepoints, the phone draws pixels.

That gives you exactly three levers, in increasing order of how well they hold up:

  1. Pick a bundled font that already has the glyphs. Termius refreshed its mobile fonts to Nerd Font v3 in June 2026, so on that client this is now a two-tap fix.
  2. Load your own patched font, which is possible in Blink Shell (via CSS), Panic’s Prompt (via an iOS configuration-profile app) and Termux (~/.termux/font.ttf), and impossible in several other clients including ConnectBot.
  3. Make the prompt not need the glyphs — p10k configure in ASCII mode, or Starship’s no-nerd-font preset. This is the only fix that also works on the borrowed laptop and the rescue console.

The rest of this covers what’s actually in those codepoints, the v2→v3 renumbering that turns icons into kanji, which mobile clients can do what, and the width problem that makes patched fonts worse on a 45-column screen than on a 200-column one.

Why the boxes appear

A terminal is a grid of cells, and each cell holds a codepoint. When the renderer is handed a codepoint its font has no glyph for, it draws a replacement box — the empty rectangle universally nicknamed tofu, or on some platforms a box containing the hex digits of the missing codepoint.

Nerd Fonts is a project that patches icon sets — Font Awesome, Material Design Icons, Octicons, Devicons and others, 3,600+ icons across 50+ patched font families (ryanoasis/nerd-fonts) — into otherwise ordinary monospace typefaces. The icons are assigned codepoints in the Private Use Area, the Unicode blocks explicitly reserved for exactly this: characters whose meaning is agreed privately between a font and the software using it.

Two consequences follow directly, and both are counterintuitive enough that people burn an evening on them:

There is no fallback. For a normal missing character — a Chinese character in a Latin font, say — the OS substitutes another installed font that has it. For Private Use Area codepoints, substitution is meaningless: no other font is supposed to have anything there, and if some font does, it will be something unrelated. Which is precisely how the kanji symptom in the next section happens.

Locale isn’t the problem. People reflexively check LANG and LC_ALL when they see boxes. UTF-8 locale settings matter for a different failure — mangled accented characters, broken box-drawing in ncurses apps, question marks where a horizontal rule should be — but a correctly transmitted PUA codepoint arrives intact and still renders as tofu if the font lacks the glyph. If your box-drawing is broken but your icons are fine, that’s a locale issue; if your icons are broken and everything else is clean, it’s a font issue. They’re rarely the same bug.

The Powerline separators specifically — the solid triangle and its outline, plus the branch and lock marks — cluster in the U+E0A0–U+E0D7 region, and they’re the most widely supported part of the set: several modern monospace typefaces (Fira Code, Source Code Pro, PragmataPro) include them natively without any patching. Everything beyond those, which is 99% of what Nerd Fonts adds, requires a genuinely patched font.

The v2 → v3 codepoint move

If your icons render as Chinese or Japanese characters rather than boxes, you’ve hit the single most confusing thing about this ecosystem, and it isn’t the phone’s fault.

Nerd Fonts 3.0 relocated the Material Design Icons block out of its legacy home at U+F500–U+FD46 and into the supplementary Private Use Area starting at U+F0001, running up to roughly U+F1AF0. The reason was a collision: the old range overlapped territory needed for other glyph sets, including CJK-related ones. The 2.3.x releases carried both the old and the new codepoints to smooth the transition; 3.0.0 dropped the old range entirely (v3.0.0 release notes). The Material Design set also roughly tripled in the process, from about 2,200 icons to around 6,800.

So an old config that hardcodes v2 codepoints, running against a v3 font, emits characters the font no longer defines. The renderer falls back — and unlike the U+E0xx region, the U+F5xx region is somewhere fallback fonts have content. On a phone loaded with CJK system fonts, that content is often a Han character. Your folder icon becomes 車.

What breaks, in practice: old Powerlevel10k preset files, hand-written tmux and vim status lines, waybar-style configs copied from a 2022 blog post, and any script that echoes raw icon bytes. What does not break: anything that resolves icons by name at runtime through a maintained library.

The fix is to regenerate the config, not to hunt for a font. Re-run p10k configure on a current Powerlevel10k, or refresh your Starship preset. Downgrading to a v2 font to make an old config work is a trap — you’ll be the only person on earth still doing it, and it locks you out of every icon added since 2023. The v3.x line is where everything lives now (v3.5.0, the “Sun-Kissed” release, is current at the time of writing).

Which mobile clients can render the glyphs

Support splits into three tiers, and the middle tier is newer than most people realise.

ClientPlatformBundled Nerd FontsYour own font fileHow
TermiusiOS + Android✅ Nerd Font v3, since June 2026❌Settings → Terminal Font (iOS) / Font & colors (Android). Bundled set: Meslo, FiraCode, JetBrainsMono, Source Code Pro, DejaVu Sans Mono, Ubuntu Mono, Cascadia Code
Blink ShelliOS/iPadOS✅ several✅ via CSSSettings → Appearance → Fonts → New Font, paste the URL of a CSS @font-face stylesheet (docs)
Prompt 3 (Panic)iOS/iPadOS—✅ via iOS font installInstall the TTF with a font app such as iFont, then Settings → Theme → Terminal Font. Only monospaced faces appear (Panic help)
TermuxAndroid—✅ file dropCopy the TTF to ~/.termux/font.ttf, run termux-reload-settings
ConnectBotAndroid❌❌No font switching in the Play Store build (issue #1952); a community PR exists but hasn’t shipped
JuiceSSHAndroid❌❌Moot in any case — it was removed from the Play Store

Three things worth pulling out of that table.

Termius mobile quietly became the low-effort answer. The bundled fonts were refreshed to Nerd Font v3 on Android on 17 June 2026 and iOS on 23 June 2026 (Android changelog, iOS changelog). If you last tried a Powerline prompt in Termius in 2024 and got tofu, that’s stale information. Loading your own font file still isn’t possible — custom fonts remains an open roadmap request — but for a stock Powerlevel10k or Starship setup, the bundled set is enough. Notably, this is on the free tier; fonts aren’t one of the paywalled features.

Blink Shell’s CSS route is the most flexible and the least obvious. Fonts are declared in a stylesheet rather than installed to the OS, and it accepts either a remote URL or a base64-embedded font (the Blink docs suggest Transfonter to generate one). There’s also a local() form, which tells Blink to look up a font already installed on iOS instead of downloading it. Blink maintains a gallery of pre-packaged Nerd Fonts at blinksh/fonts — paste the raw URL and you’re done.

ConnectBot is the outlier that catches people out. It’s still the best free, open-source, no-account Android SSH client — see ConnectBot alternatives for where it wins — but it renders with a fixed built-in typeface. Users have reported oh-my-posh prompts coming through as Han characters, which is exactly the v2/v3 fallback story above with no font-side remedy available. On ConnectBot, the server-side fix isn’t the recommended option; it’s the only one.

TermAI isn’t in that table on purpose: font-file loading isn’t the axis we compete on, and our honest answer to a tofu-filled prompt is the server-side one two sections down. More on that there.

Getting a Nerd Font onto iOS

iOS has no “install this font” action. Tapping a .ttf in the Files app does nothing useful. Fonts arrive by exactly one supported route: a configuration profile.

  1. Download the patched font on the phone — the Nerd Fonts release assets are per-family ZIPs, so grab just the family you want, not the multi-gigabyte full set.
  2. Open it in a font-provider app. AnyFont and iFont are the two commonly used ones; both take a TTF/OTF and generate a configuration profile from it.
  3. Approve the profile under Settings → General → VPN & Device Management. It’s the same mechanism used by MDM and VPN configs, so read what you’re approving.
  4. The font is now visible to any app that enumerates installed fonts.

Two limits that are easy to trip over. The app has to look for installed fonts, which most terminal apps do but not all — Prompt exposes them under Settings → Theme → Terminal Font, and filters the list to monospaced faces only, so a proportional font simply won’t appear. And Blink doesn’t need any of this; its CSS mechanism sidesteps system font installation entirely, which is why it’s the easier path if you’re already a Blink user.

Pick the Mono variant of whichever family you choose — JetBrainsMonoNerdFontMono-Regular.ttf, not JetBrainsMonoNerdFont-Regular.ttf. The next-but-one section explains why that matters more on a phone than on a desktop.

Android: Termux and everyone else

Termux makes this trivial, because Termux is a terminal emulator that owns its own rendering rather than an SSH client with a theme picker:

# from within Termux
mkdir -p ~/.termux
curl -fsSL https://github.com/ryanoasis/nerd-fonts/raw/master/patched-fonts/JetBrainsMono/Ligatures/Regular/JetBrainsMonoNerdFontMono-Regular.ttf \
  -o ~/.termux/font.ttf
termux-reload-settings

One file, one filename — it must be font.ttf — and one reload command. If nothing changes, force-close Termux and reopen it.

The catch is that Termux is a whole Linux userland to maintain, and for most people the goal was “SSH to a server,” not “run a package manager on my phone.” That trade-off is the subject of Termux alternatives and Termius vs Termux. If you’re running Termux mainly as an SSH client, the font flexibility is a real but narrow reason to keep it.

For everything else on Android, you’re choosing between Termius’s bundled v3 fonts and living without icons. That’s a smaller consideration than the ones in best SSH app for Android — key handling, SFTP, whether the session survives the screen locking — but it’s the one that makes the terminal look broken on day one, so it disproportionately colours first impressions.

Widths, alignment, and 45 columns

This is the part that’s genuinely different on a phone, and it’s why “just install a Nerd Font” is a worse answer on mobile than on a laptop.

Icons don’t all want to be one cell wide. Each patched family ships in three variants. The Mono variant forces every icon into a single terminal cell (font-patcher --mono). The default variant lets icons be double-width, so they look better in isolation. The Propo variant is proportional and has no business in a terminal at all.

Whenever the client and the font disagree about how many cells an icon occupies, everything after it on that line is drawn one column off. You notice it as a cursor that lands in the wrong place while editing a command, or a right-hand prompt that overlaps what you’re typing — the misalignment is most visible in right prompts, where the terminal has to compute a width to position the segment at all. Nerd Fonts’ own troubleshooting guidance is to switch to the Mono variant when alignment looks wrong. Use Mono on a phone. Always. The aesthetic upside of double-width icons is not worth a cursor you can’t trust when you’re typing systemctl restart one-handed at a bus stop.

Then there’s the budget problem. A phone in portrait at a font size you can actually read gives you roughly 45 to 55 columns. A stock three-segment Powerline prompt — user@host, path, git status — can eat 40 of them before you’ve typed a character. The prompt that looks magnificent on a 200-column laptop leaves you typing into a 10-column gutter.

Concrete mitigations, in the order I’d apply them:

  • Two-line prompt. Segments on line one, a bare one-character marker on line two. Both Powerlevel10k and Starship do this natively, and it’s the single biggest win on mobile.
  • Kill the right prompt. It costs columns and it’s where the width bugs live.
  • Enable transient prompt. Powerlevel10k rewrites past prompts down to a single character after each command, so scrollback isn’t 60% prompt. On a screen this small that’s the difference between reading output and scrolling for it.
  • Drop the path to a basename. Full paths are the biggest single consumer of columns and the least informative when you already know where you are.

And a broader point: horizontal space is the scarce resource in mobile SSH. It’s the same reasoning behind running long jobs in tmux on the server rather than in the foreground — design for the small screen instead of shrinking the desktop layout until it fits.

The fix that works everywhere

Everything above configures one client on one phone. Here’s the version that survives contact with reality: make the prompt degrade gracefully when the glyphs aren’t there.

Both major prompt tools treat this as a first-class case, not a fallback hack.

Powerlevel10k. p10k configure opens with a glyph-detection quiz — it renders test characters and asks whether you can see them (“Does this look like a diamond (rotated square)?”, then a lock, then a Debian logo). Answer honestly from the device you’re configuring on, and it writes a config matched to what actually renders, down to a pure-ASCII mode where icons and fancy segment separators are replaced with characters every font on earth has. Run the wizard over SSH from the phone, and the answers describe the phone.

Starship. Two presets ship for this:

starship preset no-nerd-font -o ~/.config/starship.toml         # emoji + Powerline only
starship preset plain-text-symbols -o ~/.config/starship.toml   # no Unicode at all

The no-nerd-font preset restricts symbols to emoji and Powerline sets so every module symbol renders without a patched font — the docs note it’s slated to become Starship’s default preset in a future release, which tells you where the maintainers think this argument lands. plain-text-symbols goes further and uses no Unicode whatsoever.

A cleaner variant if you don’t want to give up icons on your desktop: keep two configs and branch on $SSH_CONNECTION, or on a variable you set in your SSH config via SetEnv. Rich prompt when you’re local, austere prompt when something has SSH’d in. The phone gets a prompt that works; the laptop keeps its icons.

This is what we’d tell a TermAI user to do, and not out of modesty about the font picker. A prompt built on Private Use Area codepoints is a prompt that breaks on every terminal you haven’t personally configured — a colleague’s machine, a provider’s web console, a rescue shell, the phone you grabbed because the pager went off. Ten minutes of p10k configure buys you a prompt that’s legible everywhere. It’s the same instinct as the rest of the mobile production safety checklist: assume the environment is degraded, because at 2am it will be.

If you’d rather not hand-edit ~/.config/starship.toml on a phone keyboard, this is a reasonable thing to ask an AI assistant for — “rewrite this Starship config to use no Nerd Font glyphs and a two-line prompt.” TermAI’s assistant proposes the command and the file contents and waits for you to confirm before anything runs, which is the right posture for a config edit on a production box. The reasoning behind that design is in trusting AI shell suggestions.

Symbols-only fonts and why mobile can’t use them

On desktop there’s an elegant trick worth knowing about, mostly so you understand why it doesn’t help you here.

Nerd Fonts publishes a Symbols Nerd Font Mono (SymbolsNerdFontMono-Regular.ttf) containing only the icons and no letterforms. Terminals that support per-range font fallback can use your favourite unpatched font for text and pull only the icon codepoints from the symbols font: kitty’s symbol_map maps specific codepoint ranges to a named font, and iTerm2 has a “Use a different font for non-ASCII text” setting.

No mainstream mobile SSH client exposes that control. Termius gives you a single font from a list; Prompt gives you a single installed font; Blink gives you a CSS stylesheet, which is the closest thing to an escape hatch since CSS @font-face supports unicode-range — but that’s an unusual thing to hand-assemble and not a documented Blink feature.

So on mobile: use a fully patched font, or don’t use icons. The symbols-only approach belongs to the desktop half of your setup.

A 60-second diagnostic

Work down this list; it resolves nearly every case.

1. Establish that it’s the font. In the SSH session, print one codepoint from each region — a Powerline separator (U+E0B0), the Git branch mark (U+E0A0), a Font Awesome icon (U+F09B) and a v3-range Material Design icon (U+F0219):

python3 -c 'print(chr(0xE0B0), chr(0xE0A0), chr(0xF09B), chr(0xF0219))'

Boxes for all four means the font has no Nerd glyphs at all. Boxes for only the last one means your client’s renderer is struggling with codepoints above U+FFFF, which is where the v3 Material Design range lives. Kanji or hanzi anywhere means you’re hitting v2 codepoints and falling through to a CJK font — regenerate the config.

2. Check the client can even change fonts. ConnectBot can’t. That’s not a settings-search problem, it’s the answer.

3. If you can change it, choose the Mono variant of a v3-era family. Termius’s bundled fonts have been v3 since June 2026.

4. Separate the locale question. If ls output, htop borders or accented characters are also wrong, that’s LANG/LC_ALL and UTF-8, a different bug with a different fix — start from locale on the server.

5. Budget your columns. Two-line prompt, no right prompt, transient prompt on, basename instead of full path.

6. If you SSH from more than one device, do step 5 and skip steps 2–3. ASCII mode costs you nothing you’ll miss on a 45-column screen.

FAQ

Why does my Powerlevel10k prompt show boxes over SSH from my phone? Because the font your mobile client renders with doesn’t contain those glyphs. Nerd Font icons live in Unicode’s Private Use Area, which has no assigned meaning, so only a font explicitly patched with them can draw them — and the font that decides is the one on the phone, not the one on the server. Installing a Nerd Font on the server changes nothing: the server sends codepoints, the phone draws them.

Can Termius display Nerd Font icons on iOS and Android? Yes, since mid-2026. Termius updated its bundled terminal fonts to Nerd Font v3 on Android on 17 June 2026 and on iOS on 23 June 2026, covering Meslo, FiraCode, JetBrainsMono, Source Code Pro, DejaVu Sans Mono, Ubuntu Mono and Cascadia Code. Choose one under Settings → Terminal Font on iOS or Settings → Font & colors on Android. You still can’t load an arbitrary font file of your own — custom fonts remain an open roadmap request — but the bundled set covers the v3 codepoints.

How do I install a Nerd Font for an SSH app on iPhone? iOS has no built-in way to install a font file. Use a font-provider app such as AnyFont or iFont, which wraps the TTF in a configuration profile you approve under Settings → General → VPN & Device Management. The font then becomes available to any app that enumerates installed fonts — Panic’s Prompt lists it under Settings → Theme → Terminal Font, and shows only monospaced faces. Blink Shell skips all of this: it loads fonts from a CSS @font-face stylesheet you paste as a URL, so nothing is installed system-wide.

Why do my prompt icons show up as Chinese or Japanese characters instead of boxes? That’s the Nerd Fonts v2-to-v3 codepoint move. Material Design Icons used to sit at U+F500–U+FD46; version 3.0 relocated them to U+F0001–U+F1AF0 because the old range collided with other glyph sets. If your config still emits the old codepoints and the phone falls back to a CJK font that defines characters in that region, you get Han characters instead of icons. Regenerate the prompt config with a current tool version rather than hunting for a font that matches the old numbering.

Should I use the Mono variant of a Nerd Font on a phone? Yes. Each patched family ships in Mono, Propo and default variants; Mono forces every icon into a single terminal cell, which is what a fixed-width grid expects. The default variant permits double-width icons, and any client that disagrees with the font about an icon’s width draws the rest of the line one column off — visible as a cursor landing in the wrong place while you edit. On a phone with 45 columns to spend, that costs far more than it does on a laptop.

Is it better to fix the font or fix the prompt? Fix the prompt, if you SSH from more than one device. A prompt that depends on Private Use Area glyphs breaks on every terminal you haven’t personally configured — a colleague’s laptop, a provider’s web console, a rescue shell. Both tools ship real answers: p10k configure detects glyph support by asking whether test characters render and falls back to ASCII, and Starship has a no-nerd-font preset restricting symbols to emoji and Powerline sets, plus a plain-text preset that uses no Unicode at all.

Quick facts

  • Nerd Font icons are Private Use Area codepoints. No fallback font can supply them; the phone’s font is the only thing that matters. Installing fonts on the server is useless.
  • Nerd Fonts ships 3,600+ icons across 50+ patched families; Powerline separators cluster around U+E0A0–U+E0D7.
  • v3.0 moved Material Design Icons from U+F500–U+FD46 to U+F0001–U+F1AF0 and dropped the old range. Old configs render as tofu — or as CJK characters, when a fallback font happens to occupy the vacated region.
  • Termius mobile got Nerd Font v3 glyphs in June 2026 (Android 17 June, iOS 23 June): Meslo, FiraCode, JetBrainsMono, Source Code Pro, DejaVu Sans Mono, Ubuntu Mono, Cascadia Code. No custom font upload.
  • Blink Shell loads fonts via CSS @font-face (URL or base64); Prompt uses iOS-installed fonts and lists monospaced faces only; Termux reads ~/.termux/font.ttf after termux-reload-settings.
  • ConnectBot cannot change fonts in the Play Store build.
  • iOS font installation requires a configuration profile from an app like AnyFont or iFont, approved in Settings → General → VPN & Device Management.
  • Use the Mono variant. Single-cell icons; anything else risks column misalignment and a lying cursor.
  • You have ~45–55 columns in portrait. Two-line prompt, no right prompt, transient prompt, basename paths.
  • The portable fix is a glyph-optional prompt: p10k configure in ASCII mode, or starship preset no-nerd-font.
  • Broken box-drawing or accents is a locale bug, not a font bug — check LANG/LC_ALL for UTF-8.
Try TermAI

Free on iOS and Android. 5 AI requests/day on the free tier, plus unlimited SSH/SFTP and built-in Tailscale.

CC
Chen Chen — Founder of TermAI

Writes about mobile DevOps, terminal UX, and the surprising depth of "boring" infrastructure.