@hanxu131/pi-autotitle
v0.1.0
Published
Generate a session title from the current conversation using the current model, with smart trimming for long conversations.
Maintainers
Readme
@hanxu131/pi-autotitle
A pi extension that generates a session title from the current conversation. The /title command summarizes the conversation with the current session model, applies smart trimming for long conversations (anchor the first user message + keep a recent window), then shows a preview with confirm / regenerate / edit / cancel before setting the session display name.
Install
pi install npm:@hanxu131/[email protected]Then run /reload to activate. The command registers as /title.
For local development:
pi -e ./extensions/autotitle.tsUsage
| Command | Behavior |
| --- | --- |
| /title | Extract conversation → trim if needed → generate title with the current model → preview dialog → set session name |
| /title <custom name> | Skip the model entirely and set the session name directly |
Interactive keys (TUI)
| Key | Action |
| --- | --- |
| Enter | Accept the generated title and set it as the session name |
| R | Regenerate (unlimited retries, result updates in place) |
| E | Edit the title (prefilled with the current result; clearing the input and submitting regenerates) |
| Esc | Cancel — the existing session name is left unchanged |
Non-TUI modes (print / json / rpc) set the title directly without a dialog. Setting confirm: false in the config skips the dialog in TUI mode too.
Configuration
Config is read on every command invocation (hot-reload friendly). All keys are optional; missing keys fall back to defaults.
| File | Scope |
| --- | --- |
| ~/.pi/agent/autotitle.json | Global (all projects) |
| .pi/autotitle.json | Project-local, overrides global (only read when the project is trusted) |
Reference
| Key | Default | Description |
| --- | --- | --- |
| maxLength | 60 | Maximum title length in characters (prompt constraint, not a hard truncation) |
| prefix.enabled | true | Allow a [Type] prefix when the conversation type is clear |
| prefix.types | ["Bug", "Feature", "Question", "Refactor", "Docs"] | Candidate types for the prefix |
| language | "follow" | "follow" uses the conversation's dominant language; "zh" / "en" force a language |
| trim.threshold | 15000 | Estimated-token threshold that triggers trimming |
| trim.window | 8000 | Most-recent tokens kept after trimming |
| trim.anchorChars | 500 | Truncation length for the first user message (the topic anchor) |
| confirm | true | Show the preview dialog; false sets the title directly |
Example:
{
"maxLength": 80,
"prefix": {
"enabled": true,
"types": ["Bug", "Feature", "Question", "Refactor", "Docs"]
},
"language": "follow",
"trim": {
"threshold": 15000,
"window": 8000,
"anchorChars": 500
},
"confirm": true
}How trimming works
When the extracted conversation (user + assistant text only) exceeds trim.threshold estimated tokens, only a reduced excerpt is sent to the model:
- The first user message is kept as the topic anchor, truncated to
trim.anchorCharscharacters. - The most recent messages are kept up to
trim.windowtokens. - An omitted-messages note is inserted between the anchor and the recent window.
Edge cases
- Empty session or no extractable text → warning notification, no model call.
- No model selected (
ctx.modelundefined) → error notification, no model call. - Model call failure / empty or garbled result → error shown in the dialog (retry or cancel); the existing session name is preserved in both TUI and non-TUI modes.
- Running
/titlewhen the session already has a custom name → normal flow, the preview lets you back out.
License
MIT
