pi-sticky-header
A sticky user-prompt header for Pi's fullscreen terminal UI.
Package details
Install pi-sticky-header from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-sticky-header- Package
pi-sticky-header- Version
0.1.2- Published
- Oct 7, 2026
- Downloads
- 608/mo · 13/wk
- Author
- blocklune
- License
- MIT
- Types
- extension
- Size
- 29.9 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./sticky-header.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-sticky-header
Keep a user prompt at the top of Pi's fullscreen terminal interface. The header uses Pi's message colors and shows the message time and navigation arrows. You can expand the prompt without a change to the original message in the transcript.
Requirements
- Node.js 22.19 or later.
- Pi with the fullscreen terminal interface.
- pnpm 11.9.0 for development.
The tests use version 1.0.2 of @earendil-works/pi-coding-agent and @earendil-works/pi-tui.
In this document:
- Prompt means a user message.
- Transcript means the message area in Pi.
- Viewport means the visible area of the transcript.
- Host means the Pi application that loads this extension.
Install
Install the extension from npm:
pi install npm:pi-sticky-header
To install the latest version from GitHub, use this command:
pi install git:github.com/BlockLune/pi-sticky-header
Start Pi in fullscreen mode. The header appears when you send a prompt.
Use a local copy
Install the development dependencies:
pnpm install
Start Pi with the local extension:
pnpm dev
This command disables extension discovery for the run and loads only the local copy.
This prevents a separately installed copy of pi-sticky-header from loading at the same time.
To load the extension for one run, use this command:
pi --no-extensions -e ./sticky-header.ts
To install the local directory as a Pi package, use this command:
pi install .
Pi uses fullscreen mode by default. To select this mode explicitly, use this command:
pi --tui-mode fullscreen --no-extensions -e ./sticky-header.ts
The extension does not change the layout in regular, print, JSON, or RPC mode.
If you use /sticky in these modes, it reports that fullscreen mode is necessary.
After you change the extension files, use /reload in Pi.
Header behavior
Select a prompt
When Pi follows the end of the transcript, the header shows the latest prompt. This also applies when a short reply leaves the viewport top in an earlier turn.
When you scroll to an earlier message, the selected mode controls the header:
- auto: Show the header when the prompt's last text row leaves the viewport. Hide it while the next prompt is visible at the viewport top. This is the default mode.
- always: Show the prompt for the turn at the viewport top.
Expand a prompt
Click the header text to expand or collapse the prompt.
You can also use Pi's app.tools.expand shortcut.
Its default key is Ctrl+O.
The extension uses your configured shortcut.
An expanded prompt wraps to the terminal width. This lets you read more of a long paragraph with no line breaks. The header shows up to eight text rows and a count of the remaining rows. A collapsed prompt uses one text row. Long text ends with an ellipsis.
The header keeps two spaces between the text and the time or navigation arrows. On a narrow terminal, it reduces this gap. It hides the time first, then the arrows if necessary.
The extension keeps expansion state for each message instance. It clears this state on a session or branch change. Message times come from the active branch.
Go to another prompt
Click ↑ or ↓ to select the previous or next prompt.
You can also use /sticky prev or /sticky next.
A short message might not reach the viewport top after a scroll request. The header still shows the prompt that you selected. Scroll again to return to automatic selection.
If the header shows the latest prompt, use next again to follow new output.
Commands
| Command | Action | Alias |
|---|---|---|
/sticky or /sticky toggle |
Enable or disable the header. | — |
/sticky prev |
Go to the previous prompt. | up |
/sticky next |
Go to the next prompt. | down |
/sticky expand |
Expand or collapse the prompt. | open |
/sticky nav |
Show or hide the arrows. | buttons |
/sticky time |
Show or hide the message time. | timestamp |
/sticky auto |
Select automatic header mode. | — |
/sticky always |
Keep the header visible. | — |
/sticky status |
Show the current settings and prompt index. | — |
Development
The packageManager field selects pnpm 11.9.0.
You can use Corepack to run this version.
| Command | Action |
|---|---|
pnpm dev |
Load the local extension in Pi. |
pnpm lint |
Check the code with Oxlint. |
pnpm lint:fix |
Apply available Oxlint fixes. |
pnpm format |
Format the files with Oxfmt. |
pnpm format:check |
Check the file format without changes. |
pnpm typecheck |
Run strict TypeScript checks without output files. |
pnpm test |
Run the Vitest tests once. |
pnpm test:watch |
Run tests again when files change. |
pnpm test:coverage |
Measure V8 test coverage and check the limits. |
pnpm check |
Run all quality checks. |
pnpm hooks:install |
Install the Git hooks manually. |
pnpm pack |
Create the Pi package archive. |
Git hooks and CI
A local install sets up simple-git-hooks when the directory contains a Git repository and development dependencies.
- pre-commit: Run lint-staged to check and format staged files only.
- pre-push: Run
pnpm check.
The install script skips Git hooks in CI and directories without Git or development dependencies.
GitHub Actions runs the checks and creates a package archive on Node.js 22 and 24.
CI uses pnpm install --frozen-lockfile.
The same pnpm check command runs in CI, before a push, and before publication.
The install policy permits the esbuild build script only. It does not run the optional SDK install scripts from host dependencies.
Package structure
Pi loads TypeScript directly.
No bundler or dist/ directory is necessary.
Host packages appear in peerDependencies and devDependencies, not in dependencies.
This prevents a second runtime copy of Pi.
sticky-header.ts Extension setup, commands, shortcuts, and cleanup
src/fullscreen.ts Host layout access and transcript ScrollView selection
src/prompts.ts Prompt position measurements and selection
src/header.ts Expansion state, navigation, mouse input, and rendering
src/render.ts Text cleanup, terminal layout, message times, and colors
test/ Unit tests and native layout integration tests
Writing style
Use English for documentation, comments, test descriptions, and interface messages. Use ASD-STE100 Simplified Technical English principles for about 80% of the wording.
- Write short sentences with one main idea.
- Use the active voice when practical.
- Start procedural steps with an instruction.
- Use the same term for the same item.
- Keep technical names, API identifiers, commands, and Unicode test data unchanged.
This is a writing target, not a claim of full ASD-STE100 compliance.
Implementation and tests
The extension measures prompt positions from the rendered transcript on each frame. It does not reuse positions based only on width and direct child count. Tool boxes, nested messages, and streamed output can move prompts without a change to that count. Pi's native render caches reduce the cost of these measurements.
The measurements use the ScrollView content width. This width excludes the column for a permanent scrollbar.
The tests cover:
- Latest prompt selection at the end of the transcript.
- Streamed output and nested messages.
- Header changes during manual scrolling.
- Navigation to short messages.
- Unicode text and narrow terminals.
- Message times after branch changes and compaction.
- Session cleanup and configured shortcuts.
- Native mouse press and release events.
- Long paragraph expansion.
- Ellipsis color and spacing in light and dark themes.
- Pi's native layout engine with a fixed terminal height.
Compatibility limits
Pi has no public API to add a fixed region above the transcript.
The extension therefore uses the private fullscreen layoutRoot field.
It also reads the private text field from UserMessageComponent.
Other scroll access uses public APIs.
The extension skips setup if it cannot use the host layout.
Each native user message must remain a complete, continuous block in the rendered transcript. If another extension changes or wraps these blocks, test the two extensions together. During cleanup, this extension does not replace a root layout that another extension installed later.
Automated tests use Pi's real message components, ScrollView, and layout engine. Also test mouse input, colors, and scrolling in your terminal.