Nested markdown lists: first item of a 3rd-level list is indented 2 spaces too deep
Environment
- Claude Code 2.1.220 (native install)
- macOS (Darwin 25.5.0), node v20.19.6
What happens
When assistant output contains a markdown list nested 3 levels deep, the first item of
the deepest list is rendered 2 spaces deeper than its siblings.
Source (assistant message text):
- L1
- L2
- item A
- item B
Rendered in the terminal:
- L1
- L2
- item A <- 6 spaces
- item B <- 4 spaces
Expected: item A and item B share the same indentation.
Two-level lists render correctly.
Cause
In the markdown-to-terminal renderer, list_item stringifies each child token and
prefixes the parent indent to that whole string. A nested list is a multi-line string,
so the parent indent lands on its first line only:
case "list_item": return (e.tokens ?? []).map((child) => {
const d = render(child, { listDepth: n + 1, ... });
return `${" ".repeat(n)}${d}`; // applied to the entire multi-line string
}).join("")
Two-level lists are unaffected because the parent's n is 0.
Repro (extracted logic, plain node)
const NL = "\n";
function render(tok, n = 0, parent = null) {
switch (tok.type) {
case "list": return tok.items.map((it) => render(it, n, tok)).join("");
case "list_item": return (tok.tokens || []).map((child) => " ".repeat(n) + render(child, n + 1, tok)).join("");
case "text": return parent && parent.type === "list_item" ? `- ${tok.text}${NL}` : tok.text;
}
}
const row = (t) => ({ type: "list_item", tokens: [{ type: "text", text: t }] });
const nest = (label, inner) => ({ type: "list_item", tokens: [{ type: "text", text: label }, inner] });
const three = { type: "list", items: [nest("L1", { type: "list", items: [nest("L2", { type: "list", items: [row("item A"), row("item B")] })] })] };
console.log(render(three));
// => item A gets 6 spaces, item B gets 4
Non-workarounds
Changing the source indent width (2 / 4 / 6 spaces, tabs), changing the bullet marker,
inserting blank lines between items, and reordering items all fail — the displayed
indent is generated from listDepth, not from the source whitespace.
3 Comments
Same root cause, different trigger — no nesting required. A single-level list item that's simply long enough to word-wrap at the terminal's current width hits this identically: no 3rd-level nesting needed, just an item wider than the terminal.
This matches your diagnosis exactly — the word-wrapped text becomes a multi-line string for that list item's content, and the indent-prefixing in
list_itemonly lands on the first line, same mechanism as the nested-list case above, just produced by word-wrap instead of a child list token.Worth noting this is likely bigger-impact than the title suggests: 3rd-level nesting is rare, but any list item exceeding terminal width is common — any findings list, status report, or checklist with one long item hits it. Reproduces identically across kitty (macOS) → tmux → Linux VM, iTerm2, and Mosh on iOS, ruling out a terminal-specific cause.
Fixed in 2.1.235 — changelog: "Fixed nested markdown list items misaligning at depth 3+ and added a hanging indent to wrapped list items in the terminal UI" (https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md). Closing — reply to reopen if it still happens on the latest version.
🤖 Generated with Claude Code
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.