@gotgenes/pi-session-tools
Pi extension providing session metadata tools (naming, context) for multi-session workflows
Package details
Install @gotgenes/pi-session-tools from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@gotgenes/pi-session-tools- Package
@gotgenes/pi-session-tools- Version
2.2.0- Published
- Sep 19, 2026
- Downloads
- 180/mo · 46/wk
- Author
- gotgenes
- License
- MIT
- Types
- extension
- Size
- 68.8 KB
- Dependencies
- 0 dependencies · 3 peers
Pi manifest JSON
{
"extensions": [
"./src/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@gotgenes/pi-session-tools
Pi extension providing session metadata tools for multi-session workflows.
Tools
set_session_name
Set the current session's display name (shown in the session selector).
set_session_name({ name: "#42 Planning — Extract ExtensionPaths" })
Use a stage-encoded format to identify both the issue and workflow stage:
| Stage | Format |
|---|---|
| Planning | #N Planning — <title> |
| TDD | #N TDD — <title> |
| Build | #N Build — <title> |
| Retrospective | #N Retrospective — <title> |
get_session_name
Get the current session's display name, if one has been set.
get_session_name({})
read_session
Read the current session's entries as a structured transcript. Useful for retro lenses and cross-session context.
read_session({ types?: string[], offset?: number, limit?: number, elide_user_text?: boolean })
Parameters:
types— filter to specific entry types (e.g.["message", "compaction"]). Omit for all.offset— skip the most recent N entries after filtering, beforelimitapplies. Defaults to 0.limit— return only the most recent N entries after filtering andoffset.0returns none; a negative value is clamped to0.elide_user_text— replace each user turn's body with a[text elided: N chars]placeholder. Defaults tofalse.
The output is a human-readable transcript: numbered user/assistant turns, one-line tool call summaries with correlated result status, and metadata events (compaction, model changes, session renames).
Tool result bodies, thinking content, and image data are omitted.
A [model change] line renders only when the switch actually took effect — a marker followed by an assistant turn before the next switch or the end of entries.
A phantom switch (e.g. cycling the TUI model picker with no turn run after it) is omitted from both the transcript and the model changes count, and does not consume a slot against limit.
A [session] line marks each point where the session was renamed, which is how a multi-stage session's stage boundaries stay visible even when user bodies are elided.
Reading a long session without re-reading its tail
limit alone bounds a transcript only from the end, so reaching an early turn means asking for a larger window and re-rendering everything already read.
offset and elide_user_text address that from opposite directions, and compose:
offsetpages backward —{ limit: 40 }, then{ offset: 40, limit: 40 }, and so on. Each call renders only the entries it adds.elide_user_textshrinks every turn instead of dropping entries. On a measured 246-entry session, user bodies were 46.7% of the rendered transcript, and the elided render of the whole session cost less than three partial unelided calls did.
Neither is a filter: both leave phantom-switch suppression and the [provider/model] label on every assistant turn intact, so an attribution pass can use them freely.
In the TUI the tool row shows a compact summary by default (e.g. ✓ 42 entries — 38 messages, 18 tool calls, 2 compactions).
Press Ctrl-O to expand to the full transcript.
The model always receives the full transcript regardless of the TUI state.
1. user
How do I fix the login bug?
---
2. assistant [anthropic/claude-sonnet-4-20250514]
Let me check the auth flow.
[tool] Read — path: src/auth/login.ts → completed
[tool] Bash — command: pnpm vitest login → error
The test is failing because...
---
[compaction] Context compacted (48000 tokens before)
---
[model change] → anthropic/claude-opus-4-20250514
---
[session] → #42 TDD — Fix the login bug
---
3. assistant [anthropic/claude-opus-4-20250514]
Looking at the recent commits...
read_parent_session
Read the parent session's entries as a structured transcript when running inside a subagent. Derives the parent session file from the subagent directory layout. Returns an error if not running in a subagent context.
read_parent_session({ types?: string[], offset?: number, limit?: number, elide_user_text?: boolean })
Parameters and output format are the same as read_session.
read_session_file
Read an arbitrary session file as a structured transcript, given its path.
Useful for reading a sibling session that neither read_session (current session only) nor read_parent_session (parent-via-subagent only) can reach — for example, a peer worktree session in the parallel-worktree ship flow.
read_session_file({ path: string, types?: string[], offset?: number, limit?: number, elide_user_text?: boolean })
Parameters:
path— absolute path to a session.jsonlfile.types/offset/limit/elide_user_text— same asread_session.
Output format is the same as read_session.
Returns a status message (not an error) when the file does not exist.
list_session_files
List a working directory's session files, newest first.
Encodes the given cwd to Pi's session-directory naming convention (--<cwd with slashes replaced by dashes>-- under the sessions root) and lists the .jsonl files found there, so a caller does not have to hand-roll the encoding.
Pass a listed path to read_session_file to render it as a transcript.
list_session_files({ cwd: string, limit?: number })
Parameters:
cwd— the working directory whose session files to list (e.g. a peer worktree path). Required — there is no default, since the sibling-session use case always targets a directory other than the current session's own.limit— maximum number of paths to list, newest first. Defaults to 10. Pass a large number (e.g.1000) to list every file; there is no sentinel for "all", and0lists none.
Session directory: /Users/chris/.pi/agent/sessions/--Users-chris-worktrees-issue-546--
2 session files, newest first:
/Users/chris/.pi/agent/sessions/--Users-chris-worktrees-issue-546--/2026-07-06T10-00-00Z_.jsonl
/Users/chris/.pi/agent/sessions/--Users-chris-worktrees-issue-546--/2026-07-05T09-00-00Z_.jsonl
The count line always reports the directory's true total, and names how many paths follow when the listing is bounded:
Session directory: /Users/chris/.pi/agent/sessions/--Users-chris-pi-packages--
608 session files, newest first (showing 10):
…ten paths…
list_subagent_sessions
List a session's subagent transcripts, newest first.
Pi stores each subagent session beneath the parent session file's basename (<session>/tasks/*.jsonl), so list_session_files — which reads one directory and does not recurse — never reports them.
Pass a listed path to read_session_file to render it.
list_subagent_sessions({ path: string, limit?: number })
Parameters:
path— absolute path to the session.jsonlfile whose subagent transcripts to list. Required — there is no default, so a mistyped path can never silently answer about the current session.limit— maximum number of paths to list, newest first. Defaults to 10, with the same large-number escape hatch aslist_session_files.
Session directory: /Users/chris/.pi/agent/sessions/--project--/2026-09-06T04-26-34-471Z_01a074f7/tasks
2 session files, newest first:
/Users/chris/.pi/agent/sessions/--project--/2026-09-06T04-26-34-471Z_01a074f7/tasks/2026-09-06T17-26-06-793Z_01a077c1.jsonl
/Users/chris/.pi/agent/sessions/--project--/2026-09-06T04-26-34-471Z_01a074f7/tasks/2026-09-06T10-02-11-004Z_01a07612.jsonl
The listing reports one generation, mirroring read_parent_session's single step up — call the tool again on a returned path to reach a subagent's own subagents.
A session that spawned none renders No session files found. under the directory that would hold them; a path with no session file behind it returns a Session file not found: status instead, so the two cases stay distinguishable.
Install
pi install npm:@gotgenes/pi-session-tools
Or add it to your Pi settings (.pi/settings.json):
{
"packages": ["npm:@gotgenes/pi-session-tools"]
}
Scope and non-goals
Purpose. A multi-session workflow needs two things Pi does not otherwise expose to an extension: a way to label the current session, and a way to read a session's transcript — including a parent's or a sibling's.
In scope. Rendering a transcript more usefully for whoever reads it, and reaching a session the existing tools cannot reach. A new capability arrives as a new tool rather than as another parameter on an existing one.
Non-goals.
- Mutating transcript content. Session metadata is writable; transcript entries are read-only — no editing, redacting, replaying, or pruning.
- A raw or JSON passthrough mode.
Anything needing unrendered entries can read the session
.jsonldirectly. - Owning Pi's session storage format. The directory encoding and entry schema belong to Pi; this package matches them rather than improving them.
- Path allowlisting for
read_session_file. The agent already hasReadandBashon any file, so restricting one tool adds friction without a security boundary. - Analytics and roll-ups. Per-turn attribution and flat counts are emitted; interpreting them is the calling prompt's job.
License
MIT