Lining up the Claude Code status line with my powerlevel10k prompt: padding -2 and a 5-second refresh

I keep Claude Code in a tmux pane above a zsh pane, so its status line sits just above my zsh prompt, and the two almost matched. Both used the same powerlevel10k colours and separators, but Claude’s line started 2 columns further in and stopped wherever its text ran out. The zsh line ran the full width of the terminal, so the pair looked misaligned.
The fix was a dotted gap computed from $COLUMNS and "padding": -2, a value
the docs don’t mention. Now both prompts start at column 0 and close on the same
column, 134 of 135.
I asked Claude Code to do this. It made the measurements below in that session, and it drafted this post from them with the blog skill. I’m using “I” for the session as a whole, the same way as in my other Claude Code write-ups.
The setup
- Claude Code 2.1.316, Linux, running inside tmux
- zsh with powerlevel10k,
POWERLEVEL9K_MODE=nerdfont-v3 - A two-line p10k prompt with
·as the gap character - An existing
~/.claude/statusline-p10k.shthat already drew p10k-style segments
The two lines looked like this. Pasting from the terminal lost the Nerd Font glyphs, so the separators are missing, and I shortened the dots and rule. The third line is the tmux pane border between the two panes:
|
|
So there were two differences: the 2-column indent, and no gap filling out to
─╮.
Step 1: what the docs say
The status line docs answered half
of it. The script runs with its output captured, so tput cols can’t see the
terminal, but Claude Code sets COLUMNS and LINES before running it. That is
enough to compute a gap.
The indent looked worse:
This padding is in addition to the interface’s built-in spacing, so it controls relative indentation rather than absolute distance from the terminal edge.
Going by that, "padding": 0 would not reach the edge. I also didn’t know how
many of the COLUMNS characters the status line would really display.
Step 2: measure with a ruler in a real Claude Code
Instead of guessing, I started real claude in a throwaway tmux session and used
a ruler as its status line. --settings makes this a per-run override, so it
leaves settings.json alone.
probe2.sh:
|
|
Running it and reading the screen back:
|
|
The first run confirmed both worries:
|
|
The pane came up 135 columns wide rather than the 120 I asked for. I never found
out why, but COLUMNS reported 135, so all the numbers below use that. Varying
the offset and the padding gave:
padding |
Characters printed | Result |
|---|---|---|
0 or unset |
135 | indented 2, truncated with … |
0 or unset |
133, 132 | indented 2, truncated with … |
0 or unset |
131 | indented 2, fits |
-2 |
135 | starts at column 0, fits |
-3 |
135 | the first character is cut off |
The default padding really does leave only COLUMNS - 4 usable characters: 2
reserved on each side. A negative value is accepted, and -2 cancels the
reservation exactly. -3 goes too far and clips the line.
I also tried a leading \r and a cursor-left escape to get out of the indent.
Both runs produced no ruler at all. That was probably my shell quoting rather than
Claude Code, but I didn’t look into it, because -2 already worked.
Step 3: copy the gap from the real prompt
Before writing any drawing code, I captured the actual p10k line with its escape codes. Trimmed:
|
|
|
|
This gave me three details to copy:
- The dots are colour 240 and touch the separators, with no spaces around them.
─╮is also colour 240, and sits directly after the last segment.- The directory is plain colour 254. My script drew it bold in colour 255, which
was simply wrong. It’s 254 at
~, at~/.claudeand one level deeper.
The fix
~/.claude/settings.json:
|
|
The end of ~/.claude/statusline-p10k.sh, after the left segments are in $out
and draw_right can render the right array (the full script is
here):
|
|
A few details that matter:
${#plain}counts characters only under a UTF-8 locale. Mine is, the probe loggedLC_ALL=en_US.UTF-8, but in aClocale it would count bytes and the gap would come out wrong.- The Nerd Font separators count as one column each. The final widths match, so that holds here.
- The right segments are ordered by importance, so dropping from the end loses the 7-day usage first, then the 5-hour usage, then the context bar.
Two mistakes the real run caught
The line was one column too wide. With the gap in place, I compared the two prompts in real terminals (dots shortened here, widths as measured):
|
|
I had read the zsh line as 135 wide, because my first measurement piped grep
into wc -m, which counted the newline. It’s really 134: zsh leaves the last
column free. Hence the - 1 in cols.
Resizing left the line stale. Claude Code doesn’t rerun the script when the terminal resizes. Shrinking to 100 columns gave a truncated line:
|
|
Growing to 150 left it 135 wide, well short of the right edge. refreshInterval
reruns the script on a timer as well as on events, and after setting it to 5 both
cases came right within my 7-second wait.
Results

A terminal illustration rendered from real tmux capture-pane -e output of each
prompt at 100 columns, not a screenshot. The two captures were taken separately
and stacked in the order they appear on my screen. The boxes mark the shared
first and last columns.
| Check at 135 columns | Before | After |
|---|---|---|
| Start column | 2 | 0, same as zsh |
| Line width | ends with its text | 134, same as zsh |
| After resizing to 100 | truncated with … |
99, no truncation |
| After resizing to 150 | stays 135 wide | 149, no truncation |
The “before” resize rows were measured with padding: -2 and the gap already in
place, just without refreshInterval.
The script on its own, with a sample payload that includes context and usage data:
|
|
|
|
What this costs
padding: -2is undocumented. It works on 2.1.316, but the docs only describe padding as extra space. If a later version rejects it, the indent comes back and the line ends in…. The repair is to delete the setting and change- 1to- 4incols, which matches the 131 characters measured above.refreshIntervalruns the script every 5 seconds, includinggit status. It’s cheap in most repos, but a very large one might want a longer interval.
I kept Claude’s model, context and usage segments on the right instead of copying
zsh’s ✔ and clock. A clock would be easy to add now that the line refreshes.
Takeaways
- Measure a UI with a ruler. Printing
1234567890...through the real program settled in a few runs what the docs left open, and turned up a working value they don’t list. - Test the real program, not just the script. Piping JSON into the script gave perfect widths. The stale resize only appeared inside a running Claude Code.
- Copy from
capture-pane -e. The real escape codes showed the colours and spacing directly, including a bold directory I’d been getting wrong. wc -mcounts the newline. Useprintf '%s'when a width has to be exact. A similar width-sensitive status bar problem came up with tmux on my phone.
References
相关内容
- A Claude Code skill and subagent that write posts for this blog
- tmux 设置默认 zsh
- fzf 配置指南
- vim 打怪之旅
- Linux开发环境一键部署
支付宝
微信

william