{
  "$schema": "https://pi-tui.ratstack.sh/schema/pattern.schema.json",
  "aka": [
    "Follow-tail view"
  ],
  "animated": true,
  "apis": [
    {
      "name": "Component",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#understand-the-component-model"
    },
    {
      "name": "TUI.requestRender",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#understand-the-component-model"
    },
    {
      "name": "KeybindingsManager.matches",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#handle-keyboard-input-and-focus"
    },
    {
      "name": "matchesKey",
      "url": null
    }
  ],
  "applicability": [
    "Use this when a live output view must also permit reading earlier lines."
  ],
  "category": "rendering",
  "categoryLabel": "Rendering and performance",
  "consequences": [
    "Streaming output and manual history reading can coexist.",
    "The view must track whether tail-following is currently active."
  ],
  "family": "behavioral",
  "familyLabel": "Behavioral",
  "id": "tail-anchor",
  "implementation": [
    "Preserve manual scroll position while output grows.",
    "Recompute terminal sizing on reattachment or resize."
  ],
  "intent": "Follow new output only while the user remains at the bottom.",
  "jsonUrl": "https://pi-tui.ratstack.sh/patterns/tail-anchor.json",
  "kind": "component",
  "knownUses": [
    {
      "example": "reattach-session-list",
      "moreRefs": 0,
      "refs": [
        {
          "file": "reattach-overlay.ts",
          "lines": "18-115",
          "sha": "77df9a81",
          "url": "https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/reattach-overlay.ts#L18-L115"
        },
        {
          "file": "reattach-overlay.ts",
          "lines": "311-448",
          "sha": "77df9a81",
          "url": "https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/reattach-overlay.ts#L311-L448"
        }
      ],
      "repo": "pi-interactive-shell",
      "repoUrl": "https://github.com/nicobailon/pi-interactive-shell",
      "title": "Reattach overlay supports bounded selection and deferred refresh"
    }
  ],
  "linkedFrom": [],
  "links": {
    "agentGuide": "https://pi-tui.ratstack.sh/llms.txt",
    "index": "https://pi-tui.ratstack.sh/patterns.md",
    "skill": "https://pi-tui.ratstack.sh/skills/build-pi-tui-component.md"
  },
  "mdUrl": "https://pi-tui.ratstack.sh/patterns/tail-anchor.md",
  "motivation": "Interactive Shell's reattachment view follows the bottom only when the user has not scrolled up.",
  "name": "Tail Anchor",
  "participants": [
    {
      "name": "Component",
      "role": "Renders width-bounded lines and invalidates cached output.",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#understand-the-component-model"
    },
    {
      "name": "TUI.requestRender",
      "role": "Requests a coalesced redraw after state changes.",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#understand-the-component-model"
    },
    {
      "name": "KeybindingsManager.matches",
      "role": "Resolves input against configurable action bindings.",
      "url": "https://github.com/earendil-works/pi/blob/v1.0.3/packages/coding-agent/docs/tui.md#handle-keyboard-input-and-focus"
    },
    {
      "name": "Scroll position",
      "role": "Decides whether appended output moves the viewport.",
      "url": null
    }
  ],
  "pi": "1.0.3",
  "related": [
    {
      "how": "schedules redraws for appended output",
      "id": "render-funnel",
      "jsonUrl": "https://pi-tui.ratstack.sh/patterns/render-funnel.json",
      "mdUrl": "https://pi-tui.ratstack.sh/patterns/render-funnel.md",
      "name": "Render Funnel",
      "url": "https://pi-tui.ratstack.sh/patterns/render-funnel/"
    }
  ],
  "sampleCode": {
    "code": "// Tail Anchor: append synthetic output, following only when already at the bottom.\nimport { matchesKey, truncateToWidth, type Component } from \"@earendil-works/pi-tui\";\nimport type { PatternStory } from \"../../../src/pattern.ts\";\n\nexport const story: PatternStory = {\n  id: \"tail-anchor\",\n  title: \"Tail Anchor\",\n  kind: \"component\",\n  apis: [\"Component\", \"KeybindingsManager.matches\", \"matchesKey\", \"TUI.requestRender\"],\n  rows: 10,\n  states: [\n    { id: \"following\", label: \"Following output\", animated: true, steps: [{ type: \"tick\", ms: 600 }] },\n    { id: \"scrolled\", label: \"Reading history\", animated: true, steps: [\n      { type: \"keys\", data: \"\\x1b[A\" }, { type: \"keys\", data: \"\\x1b[A\" },\n      { type: \"tick\", ms: 600 },\n    ] },\n    { id: \"resumed\", label: \"Follow resumed\", animated: true, steps: [\n      { type: \"keys\", data: \"\\x1b[F\" }, { type: \"tick\", ms: 600 },\n    ] },\n  ],\n  setup({ theme, tui, keybindings }) {\n    const stages = [\"parse tokens\", \"check syntax\", \"compare snapshot\", \"assert boundary\"];\n    const output = Array.from({ length: 12 }, (_, i) => line(i));\n    const windowRows = 5;\n    let top = output.length - windowRows;\n    function line(index: number) {\n      return \"check \" + String(index + 1).padStart(2, \"0\") + \" · \" + stages[index % stages.length];\n    }\n    const bottom = () => Math.max(0, output.length - windowRows);\n    const timer = setInterval(() => {\n      const atTail = top === bottom(); // Test before appending, not after.\n      output.push(line(output.length));\n      if (atTail) top = bottom();\n      tui.requestRender();\n    }, 200);\n    const viewport: Component & { dispose(): void } = {\n      invalidate() {},\n      dispose() { clearInterval(timer); },\n      handleInput(data) {\n        if (keybindings.matches(data, \"tui.select.up\")) top = Math.max(0, top - 1);\n        if (keybindings.matches(data, \"tui.select.down\")) top = Math.min(bottom(), top + 1);\n        if (matchesKey(data, \"end\")) top = bottom();\n        tui.requestRender();\n      },\n      render(width) {\n        const following = top === bottom();\n        return [\n          theme.fg(\"accent\", \"Tail Anchor · synthetic test output\"),\n          theme.fg(following ? \"success\" : \"warning\", following ? \"FOLLOWING · new lines move the view\" : \"READING HISTORY · position held\"),\n          ...output.slice(top, top + windowRows).map(text => theme.fg(\"toolOutput\", truncateToWidth(text, width))),\n          theme.fg(\"muted\", \"Lines \" + (top + 1) + \"–\" + (top + windowRows) + \" of \" + output.length),\n          theme.fg(\"dim\", truncateToWidth(\"↑↓ scroll · End return to live tail\", width)),\n        ];\n      },\n    };\n    return viewport;\n  },\n};\n",
    "lang": "ts",
    "path": "stories/patterns/behavioral/tail-anchor.ts"
  },
  "states": [
    {
      "dont": false,
      "expectFail": [],
      "frames": [
        {
          "alt": "Tail Anchor, Following output state, 40 columns, dark theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-40-dark.anim.b463d2df23b6.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-40-dark.849757471c27.webp",
          "theme": "dark",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Tail Anchor, Following output state, 40 columns, light theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-40-light.anim.43dfa36bb4c1.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-40-light.c16e91310aa4.webp",
          "theme": "light",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Tail Anchor, Following output state, 60 columns, dark theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-60-dark.anim.afbca56db0dd.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-60-dark.35e085e311a1.webp",
          "theme": "dark",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Tail Anchor, Following output state, 60 columns, light theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-60-light.anim.a79b7e3ff960.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-60-light.28c80737bc00.webp",
          "theme": "light",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Tail Anchor, Following output state, 80 columns, dark theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-80-dark.anim.082f89ae54d7.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-80-dark.c1bdc42c4591.webp",
          "theme": "dark",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Tail Anchor, Following output state, 80 columns, light theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-80-light.anim.e6e1aad7b3ef.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-80-light.782ba237e5b3.webp",
          "theme": "light",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Tail Anchor, Following output state, 120 columns, dark theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-120-dark.anim.fd42ed799bf2.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-120-dark.86758a38906f.webp",
          "theme": "dark",
          "w": 2400,
          "width": 120
        },
        {
          "alt": "Tail Anchor, Following output state, 120 columns, light theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-120-light.anim.ee7f1b684f96.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/following-120-light.f3c5425fdf9e.webp",
          "theme": "light",
          "w": 2400,
          "width": 120
        }
      ],
      "how": "Show synthetic appended lines with the viewport at the tail.",
      "id": "following",
      "label": "Following output",
      "problems": []
    },
    {
      "dont": false,
      "expectFail": [],
      "frames": [
        {
          "alt": "Tail Anchor, Reading history state, 40 columns, dark theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-40-dark.anim.50669ba29ca5.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-40-dark.7f667bd15d7a.webp",
          "theme": "dark",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Tail Anchor, Reading history state, 40 columns, light theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-40-light.anim.17ded0e2bce1.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-40-light.fc56911b0610.webp",
          "theme": "light",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Tail Anchor, Reading history state, 60 columns, dark theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-60-dark.anim.0304fabb765b.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-60-dark.0c062cba53a1.webp",
          "theme": "dark",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Tail Anchor, Reading history state, 60 columns, light theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-60-light.anim.16349a25fbd8.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-60-light.448190bab5cf.webp",
          "theme": "light",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Tail Anchor, Reading history state, 80 columns, dark theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-80-dark.anim.94ae68cec2e3.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-80-dark.f1e0072a4e2c.webp",
          "theme": "dark",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Tail Anchor, Reading history state, 80 columns, light theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-80-light.anim.d37c3f172d27.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-80-light.7899d7832c60.webp",
          "theme": "light",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Tail Anchor, Reading history state, 120 columns, dark theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-120-dark.anim.2b7f663732e6.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-120-dark.bdc5804862d5.webp",
          "theme": "dark",
          "w": 2400,
          "width": 120
        },
        {
          "alt": "Tail Anchor, Reading history state, 120 columns, light theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-120-light.anim.c7f42f69eaa1.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/scrolled-120-light.ea5782d0704b.webp",
          "theme": "light",
          "w": 2400,
          "width": 120
        }
      ],
      "how": "Scroll up and retain that viewport while new lines arrive.",
      "id": "scrolled",
      "label": "Reading history",
      "problems": []
    },
    {
      "dont": false,
      "expectFail": [],
      "frames": [
        {
          "alt": "Tail Anchor, Follow resumed state, 40 columns, dark theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-40-dark.anim.58ddb9d2c1a7.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-40-dark.bfb5b9d832c0.webp",
          "theme": "dark",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Tail Anchor, Follow resumed state, 40 columns, light theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-40-light.anim.c695d570eb38.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-40-light.4e728c56609d.webp",
          "theme": "light",
          "w": 800,
          "width": 40
        },
        {
          "alt": "Tail Anchor, Follow resumed state, 60 columns, dark theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-60-dark.anim.f3710770424f.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-60-dark.6538e0a36710.webp",
          "theme": "dark",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Tail Anchor, Follow resumed state, 60 columns, light theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-60-light.anim.8f3f7ec4dfde.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-60-light.63876ba2fcb7.webp",
          "theme": "light",
          "w": 1200,
          "width": 60
        },
        {
          "alt": "Tail Anchor, Follow resumed state, 80 columns, dark theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-80-dark.anim.6eda0bce9a37.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-80-dark.07a45601ed7e.webp",
          "theme": "dark",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Tail Anchor, Follow resumed state, 80 columns, light theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-80-light.anim.e14e30adff03.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-80-light.6cdc60ac2ef9.webp",
          "theme": "light",
          "w": 1600,
          "width": 80
        },
        {
          "alt": "Tail Anchor, Follow resumed state, 120 columns, dark theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-120-dark.anim.4154e11dc2f6.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-120-dark.93ccfda296cd.webp",
          "theme": "dark",
          "w": 2400,
          "width": 120
        },
        {
          "alt": "Tail Anchor, Follow resumed state, 120 columns, light theme, 9 rows, animated",
          "animated": true,
          "animation": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-120-light.anim.91d8eada4e69.webp",
          "checks": [
            {
              "evidence": [],
              "name": "width",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "style-leak",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "hard-coded-colour",
              "status": "pass",
              "verdict": "pass"
            },
            {
              "evidence": [],
              "name": "height",
              "status": "pass",
              "verdict": "pass"
            }
          ],
          "h": 396,
          "rows": 9,
          "still": "https://pi-tui.ratstack.sh/frames/tail-anchor/resumed-120-light.b2d2e012707e.webp",
          "theme": "light",
          "w": 2400,
          "width": 120
        }
      ],
      "how": "Return to the bottom and resume following appended output.",
      "id": "resumed",
      "label": "Follow resumed",
      "problems": []
    }
  ],
  "structure": "new output + at bottom -> follow\nnew output + scrolled up -> retain\nreturn to bottom -> follow",
  "thumbnails": {
    "dark": {
      "animation": "https://pi-tui.ratstack.sh/thumbs/tail-anchor/dark.anim.5d94e24a9419.webp",
      "src": "https://pi-tui.ratstack.sh/thumbs/tail-anchor/dark.c57f68e0437d.webp"
    },
    "light": {
      "animation": "https://pi-tui.ratstack.sh/thumbs/tail-anchor/light.anim.2a48eba61f22.webp",
      "src": "https://pi-tui.ratstack.sh/thumbs/tail-anchor/light.9a96ac31bc2c.webp"
    }
  },
  "url": "https://pi-tui.ratstack.sh/patterns/tail-anchor/",
  "widths": [
    40,
    60,
    80,
    120
  ]
}
