fix(desktop): worktree support — workspace boundary + shared identity#610
Merged
Conversation
…pport Cargo's workspace discovery walks up the directory tree from desktop/src-tauri/. In git worktrees stored under .worktrees/, the walk passes through the worktree root (which correctly excludes desktop via the root Cargo.toml) then continues into the main repo root — whose exclude pattern doesn't match the worktree-relative path. A bare [workspace] table makes the crate its own workspace root so Cargo never walks higher.
Each worktree gets a unique Tauri app identifier, which means a separate data directory (fresh identity.key, empty localStorage). This forces re-onboarding on every new worktree even though the developer already has an identity from the main checkout. SPROUT_SHARE_IDENTITY=1 reuses the base dev identifier and reads the nsec from the canonical dev data dir, so worktrees share the same Nostr key, skip onboarding, and see existing config. Per-worktree icon and product name are preserved for visual distinction in the dock. Also replaces the fragile .git/worktrees/ path-pattern check with a git-dir vs git-common-dir comparison, which works for worktrees stored anywhere on disk (.worktrees/, .claude/worktrees/, or external paths).
Two fixes for the worktree identity experience: 1. instance-env.sh: keep per-worktree Tauri identifiers even when sharing the Nostr key (SPROUT_SHARE_IDENTITY=1). This preserves concurrent instance support via tauri-plugin-single-instance while still reusing the same identity. 2. onboarding hooks: when the profile query returns a real display name from the relay, auto-complete onboarding and persist the completion to localStorage. This handles the "same key, fresh data dir" case that occurs in worktrees — and also improves the general UX when importing an existing nsec into a new Sprout installation.
The hasExistingProfile change auto-skips onboarding when the mock bridge
returns a real display name for seeded identities. Two tests that seed
TEST_IDENTITIES.alice (username: "alice") with skipOnboardingSeed were
expecting the gate to open, but hasRealDisplayName("alice") returns true
and the gate auto-completes instead.
Fix the two failing tests to use blank-username identities (simulating a
real first-run user with no relay profile), and add a new test verifying
the auto-skip behavior when a profile already exists.
Also applies review feedback on instance-env.sh: quote the cat command
substitution, add a stderr warning when the canonical key is missing,
and document SPROUT_PRIVATE_KEY in the script header.
tlongwell-block
approved these changes
May 18, 2026
This was referenced May 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three fixes for running Sprout from git worktrees, plus E2E test updates and review feedback:
Cargo workspace boundary (
desktop/src-tauri/Cargo.toml) — adds a bare[workspace]table socargo metadata(and Tauri CLI) stops walking up the directory tree into the main repo root. Fixes the"current package believes it's in a workspace when it's not"error that blocksjust dev/just stagingin worktrees.Opt-in shared identity (
scripts/instance-env.sh) —SPROUT_SHARE_IDENTITY=1reads the nsec from~/Library/Application Support/xyz.block.sprout.app.dev/identity.keyand exports it asSPROUT_PRIVATE_KEY, so worktrees use the same Nostr identity as the main checkout. Per-worktree Tauri identifiers are preserved so concurrent instances don't collide.Auto-skip onboarding for existing profiles (
desktop/src/features/onboarding/hooks.ts) — when the relay already has a profile with a real display name for the current pubkey, onboarding is auto-completed and persisted to localStorage. Fixes the "half-onboarded" state where fields are prefilled but the user is still forced through the setup flow. Also improves the general UX when importing an existing nsec into a new Sprout installation.E2E test updates + shell script hardening (
desktop/tests/e2e/onboarding.spec.ts,scripts/instance-env.sh) — updates two onboarding E2E tests that relied on the old behavior (profile exists on relay but onboarding still shows), adds a new test verifying the auto-skip path, quotes theSPROUT_PRIVATE_KEYcommand substitution, and adds a stderr warning whenSPROUT_SHARE_IDENTITY=1is set but the canonical identity key doesn't exist.Worktree detection improvement
Replaces the fragile
.git/worktrees/path-pattern check with a--git-dirvs--git-common-dircomparison. This works for worktrees stored anywhere on disk (.worktrees/,.claude/worktrees/, or external paths).Usage