feat(instance): restrict Kyde to one instance, opening later launches as project tabs - #75
Merged
Conversation
… as tabs Closes #72. Every open project is already a tab, so a second `kyde <path>` from the terminal should not start a second app — it now hands the path to the running instance, which opens it as another project tab and comes forward. * `platform/instance.rs`: a unix domain socket at `$TMPDIR/kyde-<hash>.sock`, hashed over `USER|XDG_CONFIG_HOME` so separate users and config profiles never collide. A `TMPDIR` too deep for `sun_path` (~104 bytes, e.g. sandboxed or CI temp dirs) falls back to `/tmp` with the directory folded into the hash — without this, bind fails outright with "path must be shorter than SUN_LEN". * `main()` tries to deliver the launch before `Application::new()`, so a forwarded launch exits in ~30ms having created no window. Nothing listening means we are the instance, and bind after the main window opens. * The accept thread cannot touch gpui entities, so it only forwards a request over a channel to a foreground pump (the terminal EventProxy / fs-watcher pattern), which calls `open_project` and activates the window. * A socket left behind by a crash or SIGTERM is detected and unlinked before the rebind; a clean exit unlinks it on drop. * Opt-out via `KYDE_SINGLE_INSTANCE=0`, and automatically off under `KYDE_SHOT` so the screenshot suite can keep launching instances back to back. Tests: payload round-trip/degradation, the socket-path rule including the long-TMPDIR fallback, and a real listener handshake (including stale-socket cleanup). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Review failed after 2 attempt(s) (EngineError). Check the worker logs. |
Resolves the CLAUDE.md conflict: both branches appended a per-feature section at the same anchor (main's "Changelog window" from #74, this branch's "Single instance"). Rather than keep both, CLAUDE.md is trimmed to rules-and-conventions only (905 -> 327 lines). The per-feature sections narrated behaviour that the code already states, drifted out of date, and were loaded into context every session. Both conflicting sections are dropped under that policy; the single-instance facts that are genuinely rules are kept -- instance.rs on the platform/ layout line, and the note that KYDE_SHOT disables single-instance so the screenshot suite can launch back to back. Also corrects accumulated rot found while trimming: 10 dead src/*.rs paths that had moved to crates/, a views/ list missing 6 modules, "eight gpui-free crates" (now ten), "all ten crates" (now eleven), the missing kyde-local-history entry, and a stale gpui_platform reference that contradicted the gotcha saying it never existed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Closes #72.
What
Every open project is already a tab, so a second
kyde <path>from the terminal shouldn't start a second app. It now hands the path to the running instance, which opens it as another project tab and comes forward. Barekydejust raises the window.How
src/platform/instance.rs: a unix domain socket at$TMPDIR/kyde-<hash>.sock, hashed overUSER|XDG_CONFIG_HOMEso separate users and config profiles never collide.TMPDIRtoo deep forsun_path(~104 bytes — sandboxed/CI temp dirs hit this) falls back to/tmp, with the directory folded into the hash so temp dirs stay distinct. Without this,bindfails outright with "path must be shorter than SUN_LEN" and the guard silently does nothing — found while testing, not hypothetical.main()tries to deliver the launch beforeApplication::new(), so a forwarded launch exits in ~30ms having created no window and initialised no gpui. Nothing listening → we're the instance, and bind after the main window opens.Request(Open(path)/Activate) over afutures::mpscchannel to a foreground pump — the terminalEventProxy/ fs-watcher pattern — which callsopen_project+activate_window.Drop.KYDE_SINGLE_INSTANCE=0, and automatically off underKYDE_SHOTso the screenshot suite can keep launching instances back to back.Tests
TMPDIRfallback and per-profile separation.kydeactivation both work.cargo fmt+cargo clippy --workspace --all-targets --all-features -D warnings+cargo test --workspaceall green.🤖 Generated with Claude Code