pi-unshare
v0.1.0
Published
Revoke pi coding-agent session shares: find and delete the secret gists created by /share, with exact session matching and confirm-gated deletion.
Maintainers
Readme
pi-unshare
Revoke pi session shares.
pi's built-in /share uploads your entire session transcript as a secret
GitHub gist in one keystroke — and that is where the story ends. The share
URL flashes once in the TUI, nothing is persisted, and there is no built-in
way to take a share back. A "secret" gist is not private: anyone holding the
link can open it, forever.
pi-unshare completes the lifecycle.
Commands
| Command | What it does |
|---|---|
| /unshare | Find the gist(s) /share created for the current session and delete them, after one explicit confirmation |
| /unshare --yes | Skip the confirmation (required in non-interactive modes) |
| /shares | Read-only overview of every pi session share on your GitHub account, across all sessions, with revocation from the list |
Plus a footer lamp (🔗 shared) while a share of the current session is
live, and a ✂️ share revoked card in the transcript once it isn't.
Install
pi install npm:pi-unshare # once published
pi install git:github.com/SI-RUI-ZHANG/pi-unshareRequires the GitHub CLI (gh auth login) — the
same prerequisite as pi's own /share.
What it looks like
Real output from the acceptance run (print mode):
❯ /unshare
Found:
2026-07-28 18:47 https://pi.dev/session/#c0e8dfc3…
Run '/unshare --yes' to revoke.
❯ /unshare --yes
✓ revoked 2026-07-28 18:47 (c0e8dfc3) — link is dead
❯ /unshare
Nothing to do — this session's share was already revoked at 2026-07-28 18:49.In the TUI the same flow runs through native select/confirm dialogs; if the session was shared several times, revoking all of them is the default action.
How it knows which gist is yours
Every HTML export pi uploads embeds the session's UUID in a machine-readable
block. pi-unshare treats GitHub as the source of truth:
- Prune — list your gists via
ghand keep only plausible candidates: secret, a single file namedsession.html, created after this session started. - Verify — fetch a small prefix of each candidate's content and compare the embedded session UUID against the current session's UUID. Exact match or no match; no heuristics, no guessing.
- Confirm — show what was found (creation time, gist id, preview URL) and delete only after you confirm.
Shares made before this extension was installed, or from another machine,
are found just the same — nothing depends on local bookkeeping. The full
rationale, including why a /share wrapper is architecturally impossible
and the complete edge-case matrix, is in docs/design.md.
Safety model
- Nothing is ever deleted without an explicit confirmation.
- Deletion criteria are exact (session-UUID equality), never fuzzy.
- Authentication is your own
ghCLI login — the credential/shareitself uses. The extension reads no tokens and stores none. - Already deleted from the web UI? Reported and reconciled, not an error.
- Honest semantics: revoking kills the link immediately (the viewer and API 404), but copies already opened or saved by others cannot be recalled.
Configuration
~/.pi/agent/unshare.json (optional):
{ "reconcileOnStart": false }By default the extension does one quiet gist listing a few seconds after a
TUI session starts so the 🔗 shared lamp reflects reality even for shares
it never saw happen. Set reconcileOnStart: false to disable all background
network activity; the lamp then relies on what the extension itself
observed.
Limitations
- pi provides no hook at the moment
/shareruns, so the lamp cannot light up the instant a share is created — it catches up on the next/unshare,/shares, or session start. - Revocation is best-effort by nature: it deletes the gist, not the copies.
- The current
ghlogin must be the account that created the share.
Compatibility
Developed and live-tested against pi 0.81.x. The extension depends only on
the public extension API, the gist REST API, and the session-data embed
that pi's own share viewer requires — not on /share internals.
Contributing
Issues and PRs welcome. Keep the two invariants intact: no deletion path without explicit confirmation, and no deletion target without an exact session-UUID match.
