@pi-claudian/sync-session
Pi extension that syncs Pi /tree, /clone and /fork session changes into Claudian's conversation metadata.
Package details
Install @pi-claudian/sync-session from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@pi-claudian/sync-session- Package
@pi-claudian/sync-session- Version
0.1.5- Published
- Aug 4, 2026
- Downloads
- 657/mo · 657/wk
- Author
- licongy
- License
- MIT
- Types
- extension
- Size
- 37.5 KB
- Dependencies
- 0 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@pi-claudian/sync-session
A Pi extension
that bridges Claudian and Pi: it syncs Pi
session-tree changes (/tree, /fork, /clone) into Claudian's conversation
metadata, so Claudian's view of a conversation stays correct after you branch or
fork from inside Pi.
Why
Claudian stores per-conversation metadata under .claudian/sessions/conv-*.meta.json.
For Pi-provider conversations it tracks the active position in Pi's session tree
as providerState.leafEntryId, plus the sessionFile and sessionId. Claudian
never watches Pi for changes, so two Pi operations leave that metadata stale:
/treemoves the active leaf to an earlier entry within the same session file (optionally appending a branch summary). Claudian still points at the old leaf, so resuming the conversation in Claudian opens the wrong branch./fork//clonecreate a new session file and UUID. Claudian has no conversation for the new session, so it never appears in Claudian's list.
This extension closes that gap in the Pi → Claudian direction.
Protecting conversations from Claudian's missing-session cleanup
Claudian's resolveMissingConversationSession detaches a Pi session it deems
"missing": when it does, and neither a top-level nor providerState sessionId
is present, it also drops leafEntryId — which makes the conversation
unresumable (it vanishes from Claudian's list). This has caused real data
loss when Claudian false-alarms on session availability (e.g. after a version
upgrade).
This extension is the safety net: every sync — automatic or manual — also
writes the Pi session id into the conversation's top-level sessionId
(not only providerState). With the id present in both places, the cleanup
keeps leafEntryId and the conversation stays resumable. The backfill runs
automatically on every session resume, so existing conversations heal
themselves the first time you reopen them in Claudian.
Installation
pi install npm:@pi-claudian/sync-session
Usage
Automatic:
- After
/tree(or tree navigation via keybinding), the new leaf id is written into the matching Claudian conversation'sproviderState.leafEntryId. - After
/fork//clone, a newconv-*.meta.jsonis created for the forked session, copying the source title/model and pointing at the newsessionFile/sessionId/leafEntryId. The fork then shows up in Claudian's conversation list. - On session resume (Claudian opening an existing conversation), the
conversation's top-level
sessionIdis auto-backfilled if missing — silently, unless a patch was actually applied.
Manual: run /sync-session to re-sync the current leaf on demand.
The sync summary — after /tree, /fork, or /sync-session the result is
shown as a multi-line list of the session(s) affected (here a /sync-session
that was already in sync). No operation is silent:
![]()
Behavior
- Matches the Claudian meta file by Pi session id first, falling back to the
providerState.sessionFilepath (compared throughfs.realpath, so symlinked vaults match). - In addition to
providerState, every sync also (re)writes the conversation's top-levelsessionIdto the Pi session id. Claudian'sresolveMissingConversationSessiondetaches a session it deems missing: when neither a top-level norproviderStatesessionIdis present, it also dropsleafEntryId, which makes the conversation unresumable. Keeping the Pi session id in both places is the safety net that preservesleafEntryIdthrough such a false alarm. This mirrors what fork creation already writes. - Vault resolution uses the session's own home directory (
ctx.cwd, which Pi sets to the resumed session's recordedcwd— notprocess.cwd()), walking upward to the nearest.claudian/sessions. So resuming a Claudian session from a sub-directory of the vault still syncs correctly. - Fork conversations inherit the source title so they are identifiable
immediately;
@pi-claudian/sync-titlereconciles the Pi name on the next turn. - Fork creation is idempotent: if a Claudian conversation already exists for the forked session (e.g. Claudian's own fork conversion already ran), the leaf is reconciled instead of duplicating the conversation.
- Only
pi-provider conversations are touched; other providers are left alone. - Writes to Claudian are atomic (tmp file + rename) so Claudian never reads a half-written meta file.
- Silent no-op outside of a Claudian-managed vault (e.g. plain TUI sessions).
Claudian → Pi (fork conversion)
This extension does not sync Claudian-side forks back into Pi — there is no
need. When Claudian forks a Pi-based conversation it already creates the Pi
session file (and the matching .claudian/sessions conversation), so the Pi
side is already up to date after a Claudian fork.
For background: Claudian owns the Pi-session lifecycle for its own conversations and performs fork conversion in its own process, where a session-scoped Pi extension cannot reliably observe it. This extension therefore focuses on the opposite direction (Pi → Claudian), which Claudian does not do itself.
Debug
Trace matching and writes by enabling the shared @pi-claudian debug switch
(output goes to stderr):
PI_CLAUDIAN_DEBUG=1 pi # show debug output inline
PI_CLAUDIAN_DEBUG=1 pi 2>debug.log # capture to a file
Look for [pi-claudian]-tagged lines such as synced leaf: or
created fork conversation:.
License
MIT