pi-sync-suite
Cross-platform Pi extension for config sync, chat exports, safe cleanup, and native TUI controls.
Package details
Install pi-sync-suite from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-sync-suite- Package
pi-sync-suite- Version
0.1.1- Published
- Apr 28, 2026
- Downloads
- not available
- Author
- murataitov
- License
- MIT
- Types
- extension
- Size
- 391.4 KB
- Dependencies
- 0 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./dist/index.js"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
Pi Sync
Cross-platform Pi extension for syncing portable Pi configuration, exporting chats, and keeping the sync repository clean.
This package is intentionally implemented from scratch. It is inspired by the idea of config sync, but it does not reuse third-party extension code.
Install
Install from npm in Pi:
pi install npm:pi-sync-suite
Local Development
Requires Node.js 20 or newer.
npm install
npm run typecheck
npm run build
npm test
Two-device raw session sync can be smoke-tested with isolated temporary Pi agent directories:
npm run e2e:two-pi-sessions -- --local
npm run e2e:two-pi-sessions -- --remote git@github.com:you/private-test-repo.git
The GitHub mode uses a temporary pi-sync-e2e-* branch and deletes it after a successful run unless --keep-remote-branch is passed.
Pi loads the published extension from ./dist/index.js through the pi.extensions entry in package.json.
If you want to work from a local checkout instead of the published npm package:
git clone https://github.com/MuratAitov/pi-sync.git
cd pi-sync
npm install
npm run build
pi install .
Runtime setup happens inside Pi:
/sync-setup <ssh-repo-url> [pull-interval-minutes]
Use an SSH Git remote such as git@github.com:you/pi-config.git. HTTPS remotes are rejected so the extension can run Git with GIT_TERMINAL_PROMPT=0 and avoid interactive credential prompts.
Before running /sync-setup on a new machine, make sure GitHub SSH auth works:
ssh -T git@github.com
If it prints Permission denied (publickey), add a public key to GitHub. If a key already exists:
ls ~/.ssh/*.pub
pbcopy < ~/.ssh/id_ed25519.pub
Then open GitHub -> Settings -> SSH and GPG keys -> New SSH key, paste the key, and retry ssh -T git@github.com. If no public key exists, create one first:
ssh-keygen -t ed25519 -C "you@example.com"
pbcopy < ~/.ssh/id_ed25519.pub
On Linux use xclip/wl-copy or copy the file contents manually. On Windows, use PowerShell:
Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub | Set-Clipboard
The optional pull interval defaults to 1440 minutes. The extension stores its local state under the Pi agent directory, which defaults to ~/.pi/agent unless PI_CODING_AGENT_DIR is set.
Commands
/sync-setup <ssh-repo-url> [pull-interval-minutes]configures the extension./sync-pushuploads the current snapshot./sync-pulldownloads and applies the latest snapshot./sync-settingsopens the settings wizard.
Everything else is configured inside /sync-settings so the Pi command list stays small. The settings wizard currently contains:
View Status- current setupSync Mode [full/config/manual/off]- current background sync modeChat History [off/archive/resume]- current chat history behaviorConfig Paths [n]- number of extra optional paths includedCleanup [manual/auto]- current cleanup apply modeBackups [n backups]- local restore pointsEnvironment Tools [manual/auto prompt]- optional extra tool restore from a synced manifestLocal Packages [off/on]- whether to sync local path entries fromsettings.json.packagesDiagnostics- doctor / diff / log
Inside a settings section, Cancel [back] or Back [back] returns to the main settings menu. Cancel on the main menu closes settings. Descriptions are shown in dim terminal text and explain what the current setting or selectable action does.
Project Structure
src/
index.ts thin Pi package entrypoint
extension/ Pi lifecycle and command registration
config/ config defaults, loading, validation, persistence
engine/ high-level push/pull orchestration
environment/ npm/Pi package restore planning and install
git/ non-interactive Git client helpers
snapshot/ safe file staging/apply and path policy
chat/ Pi session scanning and chat export
backup/ local backup manifests and restore
cleanup/ retention planning and cleanup apply
watcher/ lightweight polling fingerprints for auto push
doctor/ diagnostics
ui/ status, dashboard, and command text rendering
utils/ cross-platform path helpers
tests/ node:test smoke and regression coverage
scripts/ development utilities
Auto Modes
/sync-setup starts in full-auto for config sync, with chat sync off by default.
full-auto: pulls on session start and on the configured interval, and polls the safe sync scope for debounced pushes.config-only-auto: same automation behavior asfull-auto; chat behavior is still controlled separately byChat History.manual: disables automatic pull and push. Use/sync-pushand/sync-pullexplicitly.off: disables automatic config and chat activity.
Change this from /sync-settings -> Sync Mode.
Safe Defaults
By default, only portable Pi configuration is staged:
- Root files:
settings.json,keybindings.json - Directories:
themes,skills,prompts
settings.json is copied without lastChangelogVersion. On restore, incoming settings are merged over local settings instead of replacing the whole file.
Pi itself handles portable package entries in settings.json.packages, such as npm:pi-lens, after the settings file changes and Pi reloads. Pi Sync keeps those entries synced, but strips local path package entries like ../../pi-sync/src or /Users/me/dev/package by default because they usually break on another machine. Enable /sync-settings -> Local Packages only when every synced device has the same local paths.
Before upload, files are scanned for common secret-like patterns such as private keys, GitHub personal access tokens, OpenAI-style keys, and obvious api_key, token, password, or secret assignments. Matching files stop the push. Symlinks are refused.
The sync repository also receives a managed .gitignore that excludes machine-local and sensitive names.
Config Paths
Use /sync-settings -> Config Paths to opt into optional safe paths:
AGENTS.mdCLAUDE.mdextensionssync-suite-chat-exports
Paths are normalized to portable forward-slash form and must stay inside the Pi agent directory. Paths containing unsafe names are refused.
The same screen also has manual include and exclude actions for advanced users.
Environment Tools
Use /sync-settings -> Environment Tools.
Environment Tools reads pi-sync-environment.json from the Pi agent directory. That file is part of the safe sync snapshot, so a new machine can pull it and then check which extra tools are missing locally.
The automatic prompt after manual /sync-pull, setup pull, or session-start pull is off by default because Pi already restores package entries from settings.json.packages. Turn on /sync-settings -> Environment Tools -> Auto Prompt only if you use pi-sync-environment.json for extra global tools outside Pi's normal package list. Background interval pulls never open an install prompt.
Example:
{
"npm": {
"typescript": "5.8.0",
"prettier": "latest"
},
"pi": [
"npm:@team/pi-extension"
]
}
Check Missing: shows installed/missing/ignored/unknown package status.Install Missing: shows the plan, then lets you install all missing packages or one selected package.Ignore Missing: hides one missing package on this device.Clear Ignored: removes the local ignore list so missing packages show again.Auto Prompt: asks after pull only when this optional tool manifest has missing packages.
Ignored packages are stored in pi-sync-environment-ignore.json. That file is local-only and is not synced, so skipping a package on one machine does not hide it on another machine.
npm packages are installed with npm install -g <package-spec> using direct process arguments, not a shell, so the same path works on macOS, Linux, and Windows. Pi packages are installed with pi install <package-spec>, including specs such as npm:@team/pi-extension. Unsafe specs with shell characters, paths, URLs, or Git/file protocols are rejected.
Chat History
Use /sync-settings -> Chat History.
No Chat Sync: do not sync chats.Readable Archive: export localsessions/**/*.jsonlto readable Markdown and JSON metadata undersync-suite-chat-exports, then sync those archive files.Resumable Sessions: sync the real Pisessions/tree so another Pi environment can show the same session tree and resume sessions.
Readable Archive mode writes:
- Markdown transcript files:
<portable-session-path>.md - JSON metadata files:
<portable-session-path>.metadata.json
Metadata includes the source path, relative session path, session id, export time, message count, skipped line count, redacted/omitted/truncated counts, source modified time, source size, and generated output paths. Malformed JSONL lines or records without recognizable message content are counted as skipped.
Readable Archive normalizes common Pi JSONL message shapes into readable user, assistant, system, and tool sections. It keeps useful surrounding text, but replaces secret-like values, internal reasoning blocks, binary/base64 image blobs, and oversized outputs with visible placeholders. Large outputs keep the beginning and end so the archive remains useful without storing thousands of noisy lines.
Readable Archive is useful for reading, search, and audit history, but it does not recreate live Pi sessions. Resumable Sessions is intentionally explicit because raw sessions may contain prompts, model outputs, tool logs, file paths, and secrets. Use it only with a private repository you control.
Cleanup
Cleanup is preview-first:
/sync-settings -> Cleanup -> Preview
/sync-settings -> Cleanup -> Run
The default retention policy keeps the newest 100 chat export files, the newest 20 backup files, and anything newer than 180 days. autoApply defaults to false, so cleanup only deletes after the settings wizard shows the candidates and the user confirms.
Cleanup only considers files under:
sync-suite-chat-exportssync-suite-backups
Backup And Restore
The Git remote is the primary backup for portable Pi state. /sync-push clones the remote if needed, stages the safe snapshot into sync-suite-repo, commits changes, and pushes them.
Before /sync-pull applies incoming remote changes, the current local snapshot is copied to sync-suite-backups/<timestamp>. Each backup contains a manifest.json and a files directory with the snapshot entries that existed locally before the pull.
Cross-machine restore from the Git remote is done by configuring the same SSH remote on another machine and running:
/sync-setup <ssh-repo-url>
/sync-pull
Pull uses git pull --ff-only and applies the safe snapshot into the Pi agent directory. settings.json is merged with local settings; other synced files and directories are replaced from the repository copy.
Local backup actions are available from /sync-settings -> Backups.
These commands operate only on local sync-suite-backups; they do not force-push or rewrite remote history.
Cross-Platform Notes
- Linux, macOS, and Windows are supported through Node.js path handling.
- The Pi agent directory is
~/.pi/agentby default, orPI_CODING_AGENT_DIRwhen set. - Paths entered in
/sync-settingsmay use/or\; they are normalized to portable/paths. - Git must be installed and available to Pi.
- SSH authentication must already work outside Pi because Git prompts are disabled.
- The sync remote should have an upstream branch configured so
HEAD..@{u}andgit pull --ff-onlywork.
What Never Syncs
The extension refuses any path containing these names:
auth.jsonsessionsunlessChat Historyis set toResumable Sessionsgitnpmbinnode_modules.env.sshsync-suite-repopi-sync-suite.json
The repository .gitignore also excludes *.log, .DS_Store, and Thumbs.db.