add encrypted Nostr session sharing#8922
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6c4c3eaa8c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| body: { deeplink: url }, | ||
| throwOnError: true, | ||
| }); | ||
| setView('sessions'); |
There was a problem hiding this comment.
Preserve target view when handling Nostr deep links
Calling setView('sessions') here assumes the caller honors the view argument, but the desktop deep-link path in App.tsx currently passes a callback that ignores _view and always navigates to /shared-session (openSharedSessionFromDeepLink(link, (_view, options) => navigate('/shared-session', ...))). As a result, opening a goose://sessions/nostr?... link from the OS imports successfully but still lands on the shared-session page instead of session history, which is a broken post-import flow for external deep links.
Useful? React with 👍 / 👎.
Signed-off-by: callebtc <93376500+callebtc@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d7ef2cf3a6
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| await importSessionNostr({ | ||
| body: { deeplink: url }, | ||
| throwOnError: true, | ||
| }); |
There was a problem hiding this comment.
Handle Nostr deep-link errors in the sessions flow
importSessionNostr is called inside the shared try block, so any Nostr import failure (invalid link, relay fetch/decrypt error, server-side 400/500) falls through to the generic catch path that always navigates to the shared-session error view. That view is specific to share-token links and shows an irrelevant shareToken for goose://sessions/nostr URLs, which breaks the intended import flow for failed Nostr links. Split Nostr handling/error routing from legacy shared-session handling so Nostr failures stay in the sessions import UX.
Useful? React with 👍 / 👎.




Overview
Category: new-feature
User Impact: Users can share and import Goose conversations through encrypted Nostr links instead of manually exchanging exported JSON files.
Problem: Session export already supports JSON files but leaves users to manage transport themselves. There was also no direct way for a receiving Goose client to fetch and restore a shared conversation from a link.
Solution: Add an isolated Nostr sharing layer that encrypts the session JSON with NIP-44 v2, publishes it as kind 30278 to configurable relays, and encodes the event reference plus decryption key in a Goose deep link. The CLI, server API, and desktop session UI now reuse that path for exporting, importing, and handling Nostr session deep links.
Changes
File changes
Cargo.lock
Adds the Nostr SDK, NIP-44 crypto, relay-pool, and supporting dependency graph needed to publish and fetch encrypted Nostr events.
crates/goose/Cargo.toml
Adds
nostr,nostr-sdk, and an optionalrustlsdependency wired into the existingrustls-tlsfeature so the live Nostr client can install a Rustls crypto provider.crates/goose/src/session/mod.rs
Exports the new isolated
nostr_sharemodule from the session domain.crates/goose/src/session/nostr_share.rs
Implements the reusable core Nostr share/import logic: default/configured relays, NIP-44 v2 encryption/decryption, kind 30278 event creation,
neventencoding, Goose deep-link creation, live publish/fetch clients, and unit tests.crates/goose-cli/src/cli.rs
Adds CLI flags for
goose session export --format json --nostr --relay ...and a newgoose session importcommand that accepts either JSON files or Nostr share links.crates/goose-cli/src/commands/session.rs
Wires CLI export/import to the shared Nostr module while preserving the existing JSON/YAML/Markdown export behavior.
crates/goose-server/src/routes/session.rs
Adds desktop-facing endpoints for sharing a session to Nostr and importing a Nostr share link back through the normal session import path.
crates/goose-server/src/openapi.rs
Registers the new Nostr session endpoints and schemas in the OpenAPI spec.
ui/desktop/openapi.json
Regenerates the desktop OpenAPI schema with the new Nostr share/import endpoints.
ui/desktop/src/api/index.ts
Regenerates the desktop API exports so UI code can call the new Nostr endpoints.
ui/desktop/src/api/sdk.gen.ts
Regenerates typed API client functions for
importSessionNostrandshareSessionNostr.ui/desktop/src/api/types.gen.ts
Regenerates request/response types for Nostr session import and share responses.
ui/desktop/src/components/sessions/SessionListView.tsx
Adds desktop UI controls to create encrypted Nostr share links from session cards and import a pasted Goose Nostr share link from Chat History.
ui/desktop/src/sessionLinks.ts
Routes
goose://sessions/nostr?...deep links through the Nostr import endpoint before returning users to the session list.Reproduction Steps
goose://sessions/nostr?...link.goose session export --session-id <id> --format json --nostrand verify it prints a Goose Nostr share link.goose session import '<goose://sessions/nostr?...>'and verify it imports the session.Validation
cargo fmtcargo test -p goose nostr_share --libcargo test -p goose-cli parses_session_export_nostr_relays --libcargo test -p goose-cli parses_session_import_nostr_link --libcargo check -p goose-serverpnpm run generate-apipnpm run typecheck