What
Replace per-render /dev/tty writes with a double-buffered framebuffer. Only changed cells are emitted per frame.
Architecture:
- Two flat 1D arrays:
_SF_FRAME_CURR[row*COLS+col] and _SF_FRAME_PREV[row*COLS+col] — each cell stores the rendered string for that position (character + ANSI codes).
- All render functions write to
_SF_FRAME_CURR instead of /dev/tty.
shellframe_screen_flush diffs CURR vs PREV, emits only changed cells as positioned escape sequences (\033[row;colH), then copies CURR → PREV.
shellframe_screen_clear resets both buffers and clears the terminal.
Migration note: Check src/screen.sh for any scaffolding already in place from task B.
Recommended approach — migrate incrementally:
- Add framebuffer array init +
shellframe_screen_flush (diff + emit)
- Migrate one render function (e.g.
shellframe_panel_render) to write to buffer; run tests
- Migrate remaining render functions one at a time, running tests after each
- Remove all direct
/dev/tty writes from render paths
- Call
shellframe_screen_flush at end of each app loop iteration in shellframe_shell
Files
src/screen.sh — framebuffer arrays, shellframe_screen_flush, clear reset
- All widget render functions — write to
_SF_FRAME_CURR instead of /dev/tty
src/shell.sh — call shellframe_screen_flush at end of loop
Done criteria
IO/timing note (CLAUDE.md §5)
The no-change flush test must exercise an actual flush call — not a mock. Terminal behavior (what triggers output) must be verified in a real environment.
Effort
XL (2–3 days)
Deps
What
Replace per-render
/dev/ttywrites with a double-buffered framebuffer. Only changed cells are emitted per frame.Architecture:
_SF_FRAME_CURR[row*COLS+col]and_SF_FRAME_PREV[row*COLS+col]— each cell stores the rendered string for that position (character + ANSI codes)._SF_FRAME_CURRinstead of/dev/tty.shellframe_screen_flushdiffs CURR vs PREV, emits only changed cells as positioned escape sequences (\033[row;colH), then copies CURR → PREV.shellframe_screen_clearresets both buffers and clears the terminal.Migration note: Check
src/screen.shfor any scaffolding already in place from task B.Recommended approach — migrate incrementally:
shellframe_screen_flush(diff + emit)shellframe_panel_render) to write to buffer; run tests/dev/ttywrites from render pathsshellframe_screen_flushat end of each app loop iteration inshellframe_shellFiles
src/screen.sh— framebuffer arrays,shellframe_screen_flush, clear reset_SF_FRAME_CURRinstead of/dev/ttysrc/shell.sh— callshellframe_screen_flushat end of loopDone criteria
shellframe_screen_flush/dev/ttywrites remain in render functionsIO/timing note (CLAUDE.md §5)
The no-change flush test must exercise an actual flush call — not a mock. Terminal behavior (what triggers output) must be verified in a real environment.
Effort
XL (2–3 days)
Deps