@burneikis/pi-sticky
v1.0.0
Published
Keeps the chat input and footer pinned to the bottom of the terminal while you scroll — works alongside pi-vim, pi-status, and any other extensions
Readme
pi-sticky
Fully vibe-coded. Might break. Works for me.
Keeps the chat input and footer pinned to the bottom of the terminal while you scroll through chat history.
Works alongside your other extensions — it does not replace the editor or footer, it pins whatever is already registered.
What it does
Uses a terminal scroll-region technique (vendored from pi-powerline-footer) to split the terminal into two zones:
- Scrollable zone — chat history
- Pinned zone — status indicator, editor (e.g. from pi-vim), widgets, footer (e.g. from pi-status)
Mouse scroll and super+up / super+down (or Page Up / Page Down) move through chat history without the input area disappearing.
Installation
pi install https://github.com/burneikis/pi-stickyThen add to your ~/.pi/agent/settings.json:
{
"extensions": [
"~/.pi/agent/extensions/pi-sticky",
"~/.pi/agent/extensions/pi-vim",
"~/.pi/agent/extensions/pi-status"
]
}Load order is required
pi-sticky must be listed first. It wraps ctx.ui.setEditorComponent and ctx.ui.setFooter before other extensions call them. If pi-vim or pi-status loads first, their registrations will not be intercepted and the sticky behavior will not work.
Compatibility
| Extension | Works? | Notes |
|---|---|---|
| pi-vim | Yes | Editor is pinned as-is, vim modes fully preserved |
| pi-status | Yes | Footer is pinned at the very bottom |
| pi-powerline-footer | No | Both extensions patch the same terminal primitives; use one or the other |
| Any setWidget extension | Yes | Widgets above/below editor are pinned alongside the editor |
Configuration
No configuration required. The extension works with sensible defaults:
- Mouse scroll enabled
- Keyboard scroll:
super+up/super+down,PageUp/PageDown,ctrl+shift+up/ctrl+shift+down - Mouse text selection and copy-to-clipboard on release
Credits
The fixed-editor/ directory is vendored from pi-powerline-footer by Nico Bailon (MIT licensed).
How it works (technical)
All extensions registered in the same session share a single ctx object (the extension runner creates it once and passes it to every session_start handler). pi-sticky uses this to intercept ctx.ui.setEditorComponent and ctx.ui.setFooter in its own session_start before other extensions run theirs.
The interception wraps each factory to capture:
- The
tuireference (the TUI instance, from the factory's first argument) - The editor renderable (the object returned by the editor factory)
Compositor installation is deferred via setTimeout(0) so it runs after all extensions' session_start handlers complete. This ensures the footer (registered by pi-status) is already in tui.children when the compositor searches for it positionally.
The pinned layout from top to bottom:
statusContainer (loading / thinking animation)
widgetContainerAbove (extensions using setWidget "aboveEditor")
editorContainer (the chat input)
widgetContainerBelow (extensions using setWidget "belowEditor")
footer (pi-status or built-in footer)These elements are hidden from the scrollable TUI render and re-rendered explicitly in the pinned cluster on every frame.
