dev_container: Align compose project name with reference CLI and recover from mixed-version duplicates - #6
Draft
antont wants to merge 173 commits into
Draft
Conversation
antont
force-pushed
the
fix-compose-project-name-derivation
branch
from
April 18, 2026 15:23
ac74dfe to
9ffed07
Compare
antont
added a commit
that referenced
this pull request
Apr 18, 2026
Introduce `pick_canonical_container`, a thin recovery layer above `find_process_by_filters`. When the multi-match detection from zed-industries#54068 trips, inspect each candidate and prefer the one whose `com.docker.compose.project` label equals `self.project_name()`. Zero or ≥2 canonical matches still fall through to the `MultipleMatchingContainers` error, preserving the safety net; only the unambiguous-recovery case is intercepted. This makes the compose-project-name fix from PR #6 a transparent upgrade: users migrating past v0.231.x to v0.232+ on an existing Zed-managed project had one container under the legacy `safe_id_lower(name)` project. After the derivation change new Zed creates one under the canonical `${folder}_devcontainer`. Without the tiebreak, the label-based lookup sees both and errors out; with it, Zed reuses the canonical one and logs the orphan's id so users can clean up on their own schedule. The multi-match detection itself (`parse_find_process_output`, `MultipleMatchingContainers`, its Display impl, the pass-through arm in `start_dev_container_with_config`) stays byte-identical with zed-industries#54068. Updates the pre-existing `check_for_existing_container_errors_when_multiple_match` test to supply non-canonical inspect overrides, so it still exercises the safety-net fall-through now that the path inspects each candidate. running 3 tests test devcontainer_manifest::test::check_for_existing_container_errors_when_multiple_match ... ok test devcontainer_manifest::test::check_for_existing_container_errors_when_none_canonical ... ok test devcontainer_manifest::test::check_for_existing_container_prefers_canonical_compose_project ... ok test result: ok. 78 passed; 0 failed (full crate) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
4 tasks
9 tasks
antont
added a commit
that referenced
this pull request
Apr 19, 2026
Introduce `pick_canonical_container`, a thin recovery layer above `find_process_by_filters`. When the multi-match detection from zed-industries#54068 trips, inspect each candidate and prefer the one whose `com.docker.compose.project` label equals `self.project_name()`. Zero or ≥2 canonical matches still fall through to the `MultipleMatchingContainers` error, preserving the safety net; only the unambiguous-recovery case is intercepted. This makes the compose-project-name fix from PR #6 a transparent upgrade: users migrating past v0.231.x to v0.232+ on an existing Zed-managed project had one container under the legacy `safe_id_lower(name)` project. After the derivation change new Zed creates one under the canonical `${folder}_devcontainer`. Without the tiebreak, the label-based lookup sees both and errors out; with it, Zed reuses the canonical one and logs the orphan's id so users can clean up on their own schedule. The multi-match detection itself (`parse_find_process_output`, `MultipleMatchingContainers`, its Display impl, the pass-through arm in `start_dev_container_with_config`) stays byte-identical with zed-industries#54068. Updates the pre-existing `check_for_existing_container_errors_when_multiple_match` test to supply non-canonical inspect overrides, so it still exercises the safety-net fall-through now that the path inspects each candidate. running 3 tests test devcontainer_manifest::test::check_for_existing_container_errors_when_multiple_match ... ok test devcontainer_manifest::test::check_for_existing_container_errors_when_none_canonical ... ok test devcontainer_manifest::test::check_for_existing_container_prefers_canonical_compose_project ... ok test result: ok. 78 passed; 0 failed (full crate) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
antont
force-pushed
the
fix-compose-project-name-derivation
branch
from
April 19, 2026 10:52
303ebca to
5244b33
Compare
…ed-industries#53100) Fixes zed-industries#42787 ## Summary - When "Go to Definition" navigates into a dependency (e.g. `.venv/`, `node_modules/`), the save dialog for new files defaulted to that directory - `most_recent_active_path` now checks the `read_only_files` setting and skips matching paths, falling back to the next eligible path, the worktree root, or the home directory ## Design tradeoffs We considered three approaches: 1. **Filter by `is_ignored`/`is_hidden`/`is_external` on worktree entries** — catches `.venv` when gitignored or when it's a dotfile, but also false-positives on directories like `.github/workflows/` that users intentionally edit. 2. **Use preview tab status** — "Go to Definition" opens files as preview tabs, so skipping preview paths targets the right intent. But it doesn't work when preview tabs are disabled, and the signal is transient (preview status changes as you interact with tabs). 3. **Use `read_only_files` setting** (this PR) — an explicit user declaration of "I never want to edit files here." If you can't edit them, you don't want to save new files next to them either. This is the clearest signal of intent and respects user configuration. The tradeoff is that `read_only_files` is empty by default, so users need to configure it. But the kind of user bothered by the save dialog defaulting to a dependency directory is the same kind of user who already configures `read_only_files` (see [zed-industries#46827](zed-industries#46827) for an example). ## Test plan - [x] Manual test: configured `read_only_files: ["**/.venv/**"]`, opened project, Go to Definition into `.venv`, created new file — save dialog defaults to project root - [x] Added `test_most_recent_active_path_skips_read_only_paths` - [x] All existing workspace tests pass Release Notes: - Fixed save dialog defaulting to dependency directories (e.g. `.venv/`, `node_modules/`) after using Go to Definition, when those directories are configured as `read_only_files`. --------- Co-authored-by: Lukas Wirth <lukas@zed.dev>
Super small update changing two instances where `DiagnosticSeverity::HINT` was set to use the color for "info". Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes zed-industries#45637 Release Notes: - Fixed various instances of hint level diagnostics using the color designated for info
…ed-industries#54183) This PR makes Zed only have one worktree picker, as opposed to a flavor of it in the title bar and another in the agent panel. It then moves it to the title bar, making it always present, so that its trigger is separate from the branch picker (which now contains only two views: branches and stashes). For the worktree picker, I'm mostly favoring the behavior we've introduced in the agent-panel-flavored version. It also updates the title bar settings migration to use the JSON `migrate_settings` helper instead of a shallow Tree-sitter rewrite, so old `show_branch_icon = true` values are promoted to `show_branch_status_icon = true` across root, platform, release-channel, and profile settings scopes. - [x] Move worktree creation logic to the `git_ui` crate to make this more generic and less agent-specific - [x] Double-check the remote use case and ensure nothing broke there - [x] Improve the UX for the detached HEAD state; better invite people to create a branch - [x] Migrate `show_branch_icon = true` to `show_branch_status_icon = true` across nested settings scopes Suggested .rules additions When migrating renamed settings keys that can appear in platform overrides, release-channel overrides, or profiles, prefer the JSON `migrations::migrate_settings` helper over shallow Tree-sitter key rewrites unless tests explicitly cover every nested scope that can contain the key. Release Notes: - Improved migration of the title bar branch status icon setting. --------- Co-authored-by: Nathan Sobo <nathan@zed.dev> Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com> Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
…cation (zed-industries#54297) Closes zed-industries#52587 Release Notes: - Improved the Dev Container suggestion notification to include the project name, with the full path shown as a tooltip.
See: https://github.com/zed-extensions/ocaml/blob/626cf8e76103fb2d8ea62fc06095df669aca4441/languages/mlx/config.toml#L3 Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [ ] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [ ] Tests cover the new/changed behavior - [ ] Performance impact has been considered and is acceptable Release Notes: - Associate .mlx extensions with OCaml
…es#54306) This change contains a number of fixes to make kept_rate more intuitive. It also adds a CLI utility to print debug info on how the metric is computed. Release Notes: - N/A
…ries#54317) This is just a refinement given it's pretty common for menus under ellipsis icon buttons to also open as a context-menu through the mouse's right-button click. This should make it slightly more convenient to interact with this menu. Release Notes: - N/A
…52525) Update all direct calls to `Editor::inline_blame_popover::take` to now be calls to `Editor::hide_blame_popover` as this ensures that the popover is also not shown in case its task still hasn't finished. This fixes a bug where the inline git blame popover could be shown even after the user had opened a modal. Release Notes: - Fixed the inline Git blame popover sometimes appearing after opening a modal. --------- Co-authored-by: dino <dinojoaocosta@gmail.com>
Fix two issues with reasoning support in the Copilot provider: - Responses API path: use the user's thinking_effort setting instead of hardcoding Medium effort - Chat Completions path: compute and pass thinking_budget when thinking is enabled, instead of unconditionally setting it to None Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [ ] Unsafe blocks (if any) have justifying comments - [ ] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [ ] Tests cover the new/changed behavior - [ ] Performance impact has been considered and is acceptable Closes zed-industries#52140 Release Notes: - Fixed a bug where copilot wouldn't use the thinking level the user's have set --------- Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de> Co-authored-by: Bennet Bo Fenner <bennet@zed.dev>
…zed-industries#54123) Stacked on top of zed-industries#54112 This is part 2 of 3 towards zed-industries#51197 More details from the original PR zed-industries#53551 This PR includes the changes from zed-industries#54112 , im not sure how to avoid that, my understanding is that after that one is merged, this PR can be rebased onto main and everything will be correct. You can also view the version of this that does reflect the changes more directly here: feitreim#1 ## Changes In this PR I added a more general string matching functionality to `fuzzy_nucleo`, in order to have proper testing for this, I also changed the command palette, tab switching picker, branch picker, and recent projects picker to use this new implementation. I think the command palette change in particular is awesome, just super nice to vaguely gesture at the command i want and have it pop right up. The main change here and departure from zed-industries#37123 is realizing that the primary reason for the regressions is actually how nucleo handles smart case, the old `fuzzy` crate only uses the smart case argument to score things differently, while nucleo actually filters on the case, eg. with smart case query "Apple" wouldnt match "apple". To get around this we always pass `CaseMatching::Ignore` to nucleo and implement the same score modifications from fuzzy in our code. There is a performance cost to that, of course, but from my testing it is fairly static, not growing as the size increases, so maybe a query takes 35 µs instead of 25 µs, but a query that takes 800 µs will only take 820 µs. Benchmark: | kind | query | size | nucleo | fuzzy | nucleo/fuzzy | |---|---|---:|---:|---:|---:| | string | 1-word | 100 | 9.15 µs | 24.6 µs | 0.37× | | string | 1-word | 1000 | 150.2 µs | 207.2 µs | 0.72× | | string | 1-word | 10000 | 1.34 ms | 2.07 ms | 0.65× | | string | 2-word | 100 | 5.16 µs | 2.94 µs | 1.75× | | string | 2-word | 1000 | 29.0 µs | 11.0 µs | 2.63× | | string | 2-word | 10000 | 210.6 µs | 55.5 µs | 3.79× | | string | 4-word | 100 | 2.57 µs | 2.33 µs | 1.10× | | string | 4-word | 1000 | 6.98 µs | 5.85 µs | 1.19× | | string | 4-word | 10000 | 20.0 µs | 12.0 µs | 1.66× | When I added the 4-word queries to the benchmarks I was actually really concerned that the performance would be awful, making it unsuitable for the command palette especially. However, I think due to the CharBag pre-filtering when the query is longer, the performance is actually way better than the 2 word case. Video: https://github.com/user-attachments/assets/3cd7221b-424f-4fd3-8df1-5543dcc340a3 Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Improved fuzzy matching in the command palette, branch picker, tab switcher, and recent projects picker to support multi-word queries. --------- Co-authored-by: Yara <git@yara.blue>
…es#54316) Follow up to zed-industries#52730. This PR adds a boolean setting `limit_content_width` in the Agent Panel settings that allows turning off the content max-width entirely, which was added for better readability. We had a handful of requests for it, so it feels fair. <img width="500" alt="Screenshot 2026-04-20 at 8 57@2x" src="https://github.com/user-attachments/assets/d2540b35-3fa8-4424-895d-dc499ac4839c" /> Release Notes: - Agent: Added a new `limit_content_width` setting in the agent panel that allows turning off the content max-width limit.
…Codestral (zed-industries#53691) Codestral and copilot has a custom menu being built out. While the common menu has the configure provider quick setting, the custom menu doesn't have them. however it is a neat feature to have and quickly switch it out. Furthermore, copilot has an option of "Use zed AI" when copilot isn't signed in. Instead add the complete list and configure provider when it is not signed in Before <img width="256" height="588" alt="Screenshot 2026-04-11 at 4 46 47 PM" src="https://github.com/user-attachments/assets/7de1c09c-a7a0-46d1-9572-fa5e970c77a8" /> <img width="230" height="480" alt="Screenshot 2026-04-11 at 4 47 00 PM" src="https://github.com/user-attachments/assets/7075538f-1966-4ece-985f-b5e0d1d50f4a" /> After <img width="259" height="663" alt="Screenshot 2026-04-11 at 5 02 48 PM" src="https://github.com/user-attachments/assets/31094f7b-8efa-488a-87d8-1998e554ec74" /> <img width="242" height="580" alt="Screenshot 2026-04-11 at 5 03 21 PM" src="https://github.com/user-attachments/assets/aba8ba09-1fbd-4c43-ba1f-af7ed51551a4" /> <img width="224" height="253" alt="Screenshot 2026-04-11 at 5 03 44 PM" src="https://github.com/user-attachments/assets/108e7b6f-1216-4a2c-b0c0-7be3dc5438b0" /> Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes NA Release Notes: - added configure provider menu item to copilot and codestral --------- Signed-off-by: Pranav <pranav10121@gmail.com> Co-authored-by: Ben Kunkle <ben@zed.dev>
…ges (zed-industries#54310) Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes zed-industries#54309 Release Notes: - Fixed an outline panel issue where the pin/unpin tooltip could show stale text after toggling.
…es#54307) Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes zed-industries#54305 Release Notes: - Fixed inconsistent keybinding hint casing in the outline panel (“Toggle Panel With …”) by using standard keybinding rendering. --------- Co-authored-by: Danilo Leal <daniloleal09@gmail.com> Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
…d-industries#54284) Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes zed-industries#54283 Release Notes: - Fixed: Git graph commit detail header now uses “1 Changed File” when exactly one file changed, and “N Changed Files” otherwise, instead of always saying “Changed Files”. --------- Co-authored-by: Kunall Banerjee <hey@kimchiii.space>
…ries#54300) Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes zed-industries#54299 Release Notes: - N/A --------- Co-authored-by: Danilo Leal <daniloleal09@gmail.com> Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
## Context `ctrl-n` / `cmd-n` doesn't work on the Welcome tab. The global binding lives under `Workspace && !Terminal` (macOS) and similar contexts that don't include Welcome. The fix just adds the same binding to the Welcome context block on all three platforms — same approach the font-size and recent-project shortcuts already use there. Closes zed-industries#52426 ## Demo ### Before: https://github.com/user-attachments/assets/69becde8-25d2-45e3-9e7c-416b7937bd17 ### After: https://github.com/user-attachments/assets/6d9ede76-7adb-4527-bfef-c18d5b8a4fb4 ## How to review One line added per platform keymap file. Check that `ctrl-n` / `cmd-n` maps to `workspace::NewFile` in the `Welcome` block of: - `assets/keymaps/default-macos.json` - `assets/keymaps/default-linux.json` - `assets/keymaps/default-windows.json` ## Self-review checklist - [x] I've reviewed my own diff for quality, security, and reliability - [ ] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed `ctrl-n` / `cmd-n` (New File) not working on the Welcome tab Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
This PR adds support for rendering **Netpbm** image formats (`.pbm`, `.ppm`, `.pgm`) within Zed's built-in image viewer. These formats are particularly useful for projects that want minimal external dependencies, a common scenario in academic environments and low-level graphics programming. Since the underlying `image` crate and `GPUI` already provide support for these codecs, this change explicitly exposes the `Pnm` variant within `gpui::ImageFormat` by mapping it to `image::ImageFormat::Pnm`. ## Screenshots/Examples Below is an example of `.pbm`, `.ppm`, and `.pgm` files being rendered correctly in the image preview (images taken from https://filesamples.com): <img width="1917" height="1012" alt="pnm_example" src="https://github.com/user-attachments/assets/0056133f-908c-4c91-ba9d-53aef0657b05" /> Release Notes: - Added support for PNM image previews (`.pbm`, `.ppm`, `.pgm`).
…#53195) ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [X] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes zed-industries#52942 ## Demo: ### Before: https://github.com/user-attachments/assets/fd3b69fc-468a-4fd1-82c9-4f1aa83c6474 ### After: https://github.com/user-attachments/assets/0a6c70a9-0a4a-4657-9fe8-21988fff9e80 ## Release Notes: - Fixed play button appearing in gutter for unsaved buffers where clicking it was a no-op. --------- Co-authored-by: Lukas Wirth <lukas@zed.dev>
Review feedback: derive_project_name has two gaps vs. `getProjectName`
in `src/spec-node/dockerCompose.ts`.
1. `docker_compose_manifest()` builds compose file paths by joining
`self.config_directory` with each raw `dockerComposeFile` entry
verbatim, so entries like "subdir/../docker-compose.yml" yield a
`PathBuf` with unresolved `..`. `derive_project_name` compares
`parent()` against `<workspace>/.devcontainer` and extracts
`file_name()` from that raw parent — no normalization — so a file
semantically under `.devcontainer` takes the wrong branch. Rust's
`Path::file_name` returns `None` on a path ending in `..`, which
collapses to `workspace_fallback` bare (not even the CLI's
rule-4 `${workspace}_devcontainer`).
2. `is_missing_file_error` comment and doc mirror the CLI's narrow
`ENOENT`/`EISDIR` swallow for the `.env` read, but the code catches
`NotADirectory` (ENOTDIR) instead of `IsADirectory` (EISDIR). The
prior unit test locked in the mismatch.
Failing output captured before fix:
running 2 tests
test …::derive_project_name_normalizes_compose_path_for_rule_4 ... FAILED
test …::is_missing_file_error_only_accepts_notfound_and_isadirectory ... FAILED
---- derive_project_name_normalizes_compose_path_for_rule_4 ----
assertion `left == right` failed
left: "project"
right: "project_devcontainer"
---- is_missing_file_error_only_accepts_notfound_and_isadirectory ----
assertion failed: is_missing_file_error(&is_a_dir)
test result: FAILED. 0 passed; 2 failed; 0 ignored.
GREEN lands in the next commit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Fixes the two bugs pinned by 6d41917: 1. `derive_project_name` now normalizes the compose-file parent and the `<workspace>/.devcontainer` target path via `util::normalize_path` before comparing. `docker_compose_manifest()` joins `self.config_directory` with each raw `dockerComposeFile` entry verbatim, so paths can carry `..` components. Without normalization, `subdir/../docker-compose.yml` under `.devcontainer/` missed rule 4 and `.devcontainer/../docker-compose.yml` had `None` from `file_name()` on the parent. The reference CLI's `getProjectName` does `path.resolve()` before its own branch, so this matches upstream. 2. `is_missing_file_error` now matches `IsADirectory` (EISDIR) instead of `NotADirectory` (ENOTDIR). The reference CLI's narrow `.env` swallow is `ENOENT || EISDIR`; the previous code swallowed `ENOENT || ENOTDIR`, which meant a `.env` that was actually a directory would propagate as a hard `FilesystemError` instead of falling through to rule 3–5. Both RED tests from 6d41917 now pass. Full crate green: 87 passed.
Revert the pick_canonical_container stack. When multiple containers match the identifying labels, propagate MultipleMatchingContainers (introduced in the detection commit) untouched rather than trying to prefer one. The mixed-version case — legacy and new containers coexisting — is a transient edge that does not justify permanent code. Users with duplicate legacy containers can clean them up once; the detection error surfaces the mismatch with instructions. Removes: - pick_canonical_container method - DockerConfigLabels.compose_project field and its serde rename - Tests and helpers specific to the tiebreak Per review on zed-industries#54302.
Replace serde_yaml_ng with yaml-rust2 for the single call site in compose_fragment_declares_name. yaml-rust2 is already a transitive workspace dependency (via tree-sitter-yaml and, until this commit, serde_yaml_ng → unsafe-libyaml), so this is a net reduction of one direct workspace dependency. The existing test covering block-style, quoted-key, flow-style, and parse-failure inputs passes unchanged. Per review on zed-industries#54302.
Testing out Niko's new SDK design Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - N/A
antont
force-pushed
the
fix-compose-project-name-derivation
branch
from
April 22, 2026 15:03
2418589 to
ca9e505
Compare
Remove test_deserialize_single_json_object — it just tests that serde deserializes a JSON object, which is serde's responsibility, not ours. The remaining three tests still lock in the actual contract: NDJSON is rejected, empty output is None, empty object is None.
…4511) The `project_name` worktree setting was added in zed-industries#36713 to let users override the name shown in the window title. Its description ("The displayed name of this project. If left empty, the root directory name will be displayed.") suggests broader coverage, and zed-industries#46440 reports the reasonable expectation that it should also apply in the project switcher. In practice the setting has only ever affected `Workspace::update_window_title`, so everywhere else (recent projects, the multi-worktree pane, ...) keeps falling back to the worktree root name. Rather than plumb the setting through each of those surfaces, I'm removing it. Having a project-level setting control how your editor displays the project has downsides. For example it means a checkout can dictate UI in someone else's Zed. The natural home for a custom display name is the workspace DB, set from the UI, which is what we should do if we want this feature back. If you want this back, the path forward is to store the display name in `WorkspaceDb`, expose a UI affordance to edit it, and read it from `update_window_title`, `recent_projects::get_recent_projects` / `get_open_folders`, and any other places that currently derive a display name from the worktree root. Closes zed-industries#46440 Release Notes: - Removed the `project_name` project setting. It only ever affected the OS window title, and the expectation that it would show up in the project switcher and elsewhere is better served by a future UI-driven, per-workspace setting stored locally.
Adds documentation for the Parallel Agents feature. ## Changes - **New page** `docs/src/ai/parallel-agents.md`: covers the Threads Sidebar component, switching threads, the archive and search, importing ACP threads, running multiple threads, multiple projects, worktree isolation, and the default layout change - **`docs/src/ai/overview.md`**: rewrites the Agentic editing section to lead with the Threads Sidebar, adds Parallel Agents to the Getting started links - **`docs/src/ai/agent-panel.md`**: adds a cross-link to the Threads Sidebar in Creating New Threads, removes the Navigating History section (now covered in the Threads Sidebar docs) - **`docs/src/SUMMARY.md`**: adds Parallel Agents between External Agents and Inline Assistant Release Notes: - N/A --------- Co-authored-by: Katie Geer <katie@zed.dev> Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com> Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
## Summary Closes zed-industries#53570 - `o` and `O` in normal mode were unconditionally copying the current line's indentation into the new line, ignoring the `auto_indent` setting entirely - When `auto_indent: "none"` is set, new lines created by `o`/`O` now start at column 0 as expected - When `auto_indent` is `preserve_indent` or `syntax_aware`, behavior is unchanged The fix reads `language_settings_at` for the relevant row and splits edits into two paths: `editor.edit()` (no autoindent) for `None`, and `editor.edit_with_autoindent()` for everything else — mirroring the approach already used by the non-vim `Newline` action. ## Test plan - Added `test_o_auto_indent_none`: verifies `o`/`O` produce column-0 lines with `auto_indent: "none"`, including edge cases (first line, empty line) - Added `test_o_preserve_indent`: verifies `o`/`O` copy the current line's indentation with `auto_indent: "preserve_indent"` (regression guard) - Existing neovim-backed tests (`test_o`, `test_insert_line_above`, `test_o_comment`) continue to pass Release Notes: - Fixed vim `o`/`O` commands ignoring the `auto_indent: "none"` setting, causing new lines to inherit indentation instead of starting at column 0
…gex-special characters (zed-industries#54422) Closes zed-industries#54331 Updates zed-industries#50848 Release Notes: - Fixed hang in replace all when the query contained non-ASCII text and regex-special characters
…ndustries#54356) Closes zed-industries#49581 Adds a `line_ending` language setting that controls how line endings are handled for new files and during format/save: - `detect` (default) — detects existing line endings; new files use the platform default - `prefer_lf` / `prefer_crlf` — sets LF or CRLF for new files and files with no existing convention, while preserving existing files - `enforce_lf` / `enforce_crlf` — normalizes all line endings to LF or CRLF on every format/save The setting can be configured globally, per-language, or via `.editorconfig`'s `end_of_line` property (which maps to `enforce_lf` / `enforce_crlf`). Release Notes: - Added `line_ending` setting to control how line endings are handled for new files and normalized on save. - Added support for `.editorconfig` `end_of_line` property to enforce line endings. --------- Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
…elf (zed-industries#54204) Previously, we would show these checkboxes whenever hovering anywhere in the `entries` group, which covers all headers and status entries. This seems excessive, and also has a problem that the header checkboxes disappear when the mouse moves over a non-header (status entry) checkbox, presumably because those have `stop_propagation`. Now, we only show the checkbox for a header when that specific header is hovered. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - N/A
Self-Review Checklist: Closes zed-industries#53863 Updates zed-industries#53920 Updates zed-industries#51949 Updates zed-industries#45166 Release Notes: - Updated auto_save_on_focus_change to handle modals better.
…ches (zed-industries#54519) Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes zed-industries#54517 Release Notes: - Fixed Command Palette behavior where footer actions could still route to a fallback hidden command when search returned no matches.
Previously hitting `Publish` in the git panel would silently fail with no error message if the git repo was new or didn't have a remote. Now, when hitting `Publish` or attempting to push when there is no remote using keyboard shortcuts, or using `Push To` or force push options, an error message will be displayed. <img width="1135" height="522" alt="Screenshot 2026-04-22 at 10 02 26 AM" src="https://github.com/user-attachments/assets/93c5e7ee-371e-4c2c-961b-42501cbd7119" /> <img width="1135" height="522" alt="Screenshot 2026-04-22 at 10 02 36 AM" src="https://github.com/user-attachments/assets/a923e5f2-4099-45b5-8fe2-eb78f4fc9f10" /> Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed handling of `git push` when there is no remote available to push to
Move `..`-resolution from `derive_project_name` to `docker_compose_manifest` so every downstream consumer of `DockerComposeResources.files` (fragment reads, project-name derivation, `docker compose -f` invocations) sees resolved paths. Per Kyle's review on zed-industries#54302 (discussion_r3125767714). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
It's currently not valid to limit the syntax highlighting cursor in this way, because it prevents us from recognizing important patterns like `(function_item name:(identifier) @function` if the function exceeds the context length, which is common. We'll need to think harder about whether there's a different solution the problem of slow queries in the presence of large parse errors. Reverts zed-industries#52674
…#49106) Release Notes: - Fixed heredoc commands failing with "syntax error: unexpected end of file" in AI Agent shell execution Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Jakub Konka <kubkon@jakubkonka.com>
Spelling flagged by upstream CI's typos check. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…abs open (zed-industries#51434) Release Notes: - helix: Fix some commands that you might want use when you have no panes open, like project or symbol search. --------- Co-authored-by: Jakub Konka <kubkon@jakubkonka.com>
Self-Review Checklist: - [Yes] I've reviewed my own diff for quality, security, and reliability - [N/A] Unsafe blocks (if any) have justifying comments - [N/A] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [N/A] Tests cover the new/changed behavior - [N/A] Performance impact has been considered and is acceptable Release Notes: - N/A
Closes zed-industries#52629 ## Overview Adds a generic editor-owned navigation overlay primitive for rendering target ranges, anchored labels, and fade ranges. This gives [Helix amp jump](zed-industries#43733), [Beam Jump](zed-industries#45387), and future jump-style features (like [this one](zed-industries#14801)) a shared editor abstraction for overlay layout and paint instead of feature-specific render paths. ### Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - N/A
…48847) Release Notes: - Fixed an issue where pressing `Escape` in the search bar did not dismiss it when using the Helix keymap, while it worked correctly in Vim mode. Co-authored-by: buildingvibes <buildingvibes@users.noreply.github.com> Co-authored-by: Jakub Konka <kubkon@jakubkonka.com>
…ies#54532) Adds a link to the Tasks section of the docs from the Worktree Isolation section in parallel-agents.md Release Notes: - N/A
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
This PR ships two related changes together, because the second keeps the first from regressing upgraders:
Match
@devcontainers/cli's fullgetProjectNameprecedence. Replacessafe_id_lower(devcontainer.json's name)with the same five-step chain the reference CLI walks (seesrc/spec-node/dockerCompose.tsin devcontainers/cli):COMPOSE_PROJECT_NAMEfrom the local environment.COMPOSE_PROJECT_NAME=in the workspace.envfile.name:on the merged compose config, when at least one fragment declared it explicitly.${workspaceFolderBasename}_devcontainer— only when the first compose file's directory is<workspace>/.devcontainer/.The old Zed implementation diverged at every one of those inputs: any user setting
COMPOSE_PROJECT_NAME, shipping a.envwith one, declaring a top-level composename:, or pointingdockerComposeFileoutside.devcontainer/(e.g."../docker-compose.yml") got a different project namespace than the CLI and VS Code, producing two compose projects for the same folder.Mixed-version tiebreak. When
check_for_existing_container's label-based lookup returns two candidates (because a pre-fix Zed left a container under the legacy project name alongside a CLI-style one), prefer the container whosecom.docker.compose.projectlabel matches the value the new derivation produces. Log the ignored legacy orphan. Two non-canonical candidates still surfaceMultipleMatchingContainers(dev_container: Detect error state when docker ps returns duplicate containers zed-industries/zed#54068's safety net).Without the tiebreak, the derivation fix would turn the existing silent-duplicate state on upgrade into a hard
MultipleMatchingContainerserror. Shipping both makes the change a transparent upgrade in the common case while preserving CLI-parity in the long tail.As a concrete example exercising rule 4 — a folder
devcontainer-compose-test/with"name": "Compose Duplicate Repro"anddocker-compose.ymlin.devcontainer/, no.envand no explicit composename::compose_duplicate_reprodevcontainer-compose-test_devcontainerdevcontainer-compose-test_devcontainer(matches CLI)devcontainer-compose-test_devcontainer, logs thecompose_duplicate_reproorphan.Adds a small
sanitize_compose_project_name()helper that implements the CLI's sanitization rules (lowercase + strip[^-_a-z0-9]) — notably preserving hyphens, whichsafe_id_lowerwould have replaced with underscores.Adds two helpers used by the precedence walk:
parse_dotenv_compose_project_name— line scan extractingCOMPOSE_PROJECT_NAME=…from the workspace.env, matching the subset the CLI's regex dotenv reader recognizes.compose_fragment_declares_name— parses a compose fragment viaserde_yamland checks for anamekey on the root mapping (block, quoted, or flow style all work), matching the CLI's ownyaml.load.docker compose configalways injectsname: devcontainerinto its merged output when no fragment declared one, so rule 3 needs to distinguish the user-provided case from the injected default — this helper supplies that signal. On YAML parse failure it returns "not declared" (rule 4 applies), matching the CLI's fallback.project_name()becomes async and fallible (async fn project_name(&self) -> Result<String, DevContainerError>) so it can load the.envfile and each compose fragment viaself.fs.load. Four call sites now.await?the derivation. Real I/O errors on the.envread propagate asFilesystemError(matching the CLI's narrowENOENT/EISDIRswallow); fragment-rescan read errors are logged and skipped (matching the CLI's broader try/catch over its fragment read + parse).The
namefield is still used as the features image-tag prefix (generate_features_image_tag); only the compose project namespace is decoupled from it.Adds a
compose_projectfield onDockerConfigLabels, serde-renamed tocom.docker.compose.project, consumed by the tiebreak's inspect call.New dependency:
serde_yaml_ngThis PR adds a new workspace dependency on
serde_yaml_ng = "0.10"(a YAML parser), pulled in only bydev_container. Its entire use is one call incompose_fragment_declares_namethat parses a compose fragment to check whether the root mapping has an explicitname:key. That signal is required bygetProjectNamerule 3 —docker compose configinjects a defaultname: devcontainerinto its merged output whenever no fragment declared one, so the only way to distinguish the user-declared case from the injected default is to re-parse each fragment the user wrote. The reference CLI does this viayaml.load. We originally tried a line-based scanner here; a reviewer correctly pointed out (zed-industries#9 in the commit list) that it missed quoted keys and flow-style root mappings, so the scanner was replaced with a real YAML parse.serde_yaml_ngrather thanserde_yamlbecause dtolnay'sserde_yamlis archived and publishes as0.9.34+deprecated.serde_yaml_ng(acatton) is an active minimal fork with attribution intact, declared drop-in compatibility withserde_yaml'sValue/from_str/MappingAPI, and no outstanding community concerns. The other notable fork,serde_yml(sebastienrousseau), is also archived and has community concerns about stripped attribution from the dtolnay original — skipped on both counts.Happy to take guidance here — swap to a different crate, keep the deprecated
serde_yaml, or anything else the reviewers prefer.Why
Full write-up with verified fixtures and captured output: #5
Three failure modes from the same root cause, all resolved by this change:
devcontainer up(or Zed on one version and VS Code on another) creates two compose projects with identicaldevcontainer.local_folder+devcontainer.config_filelabels, breaking the spec's uniqueness invariant.devcontainer.jsonwith the samename, Zed uses the same compose project for all of them; Compose reuses stateful siblings (db, cache, localstack) by config-hash, so worktree B silently inherits worktree A's database. Fixture + captured output: https://github.com/antont/zed-devcontainer-db-share-repro@devcontainers/cliso it used the reference derivation. The collision shows up when new Zed has already created a container under the name-field project and a CLI-derivation tool (old Zed,devcontainer up, VS Code) runs against the same folder afterwards — the reverse order does not duplicate, because new Zed's label-first lookup reuses the existing CLI-style container. So a v0.231.x → v0.232+ upgrade by itself isn't a reproducer; a mixed-version rhythm where the name-field container was created first is. The tiebreak lets new Zed transparently adopt the canonical container when both already exist.This PR is a companion to zed-industries#54068 (duplicate-detection on the lookup side). This one fixes the root cause and handles graceful recovery; that one catches remaining genuine ambiguity on the label-lookup path.
Migration / compatibility
Existing Zed-created containers (under the old
safe_id_lower(name)project) are still found viacheck_for_existing_container, which looks them up bydevcontainer.local_folder+devcontainer.config_filelabels, not by project name. So on first run after upgrade, the existing container is reused; the tiebreak covers the case where both a legacy container and a CLI-style container coexist. No user action required.Test plan
cargo test -p dev_container --lib— 86 passed, including:sanitize_compose_project_name_matches_cli_rules--project-nameassertion added totest_spawns_devcontainer_with_docker_composecheck_for_existing_container_prefers_canonical_compose_projectcheck_for_existing_container_errors_when_none_canonicalshould_deserialize_inspect_with_compose_project_labelderive_project_name_env_wins_over_everythingderive_project_name_dotenv_wins_over_compose_and_fallbackderive_project_name_compose_name_wins_over_fallbackderive_project_name_skips_compose_name_when_not_explicitly_declaredderive_project_name_omits_suffix_when_compose_file_outside_devcontainer_dircompose_fragment_declares_name_detects_top_level_name_key(covers block, quoted-key, and flow-style roots, plus parse failure → not-declared)is_missing_file_error_only_accepts_notfound_and_notadirectorycargo fmt --all— cleancargo clippy --workspace --release --all-targets --all-features -- --deny warnings— cleanzedfrom this branch.docker ps -a --filter "label=devcontainer.local_folder=$PWD" -q | xargs -r docker rm -fzed --dev-container /Users/antont/src/devcontainer-compose-test→ Zed creates container under projectdevcontainer-compose-test_devcontainer(wascompose_duplicate_reprobefore the fix).devcontainer up --workspace-folder $PWD→ CLI reports the samecontainerIdZed created; no second compose project is introduced.devcontainer-compose-test_devcontainer-app-1(IDb0cfb5836f92),composeProjectName: "devcontainer-compose-test_devcontainer"reported by both tools.Commits
--project-nameexpectation to the CLI derivation, no production change. Commit message captures the exact failure output.${folderBasename}_devcontainerbranch), adds the CLI-parity sanitization helper + unit test. Remaining rules land in commits 7–8.pick_canonical_container, routes theMultipleMatchingContainerserror arm through it.com.docker.compose.projectlabel rename, confirming the new typed field round-trips.check_for_existing_containertoresult => resultso the multi-match interception stands out as the only non-trivial arm. No behavior change.derive_project_namehelper and five focused tests (one per rule plus the rule-3 edge case). Commit message captures the RED output.derive_project_name, addsparse_dotenv_compose_project_nameandcompose_fragment_declares_namescanners, and convertsproject_name()to async so it can load.envand each compose fragment..envread failures now propagate unless the error isNotFound/NotADirectory(matching the CLI's narrowENOENT/EISDIRswallow), preventing silent fallback to a non-canonical project name when a workspace has an unreadable.env; (b)compose_fragment_declares_namenow parses fragments as YAML viaserde_yamlrather than line-scanning, so quoted keys and flow-style root mappings are honored just like the CLI'syaml.load.project_name()becomesResult<_, DevContainerError>; four call sites propagate with?.getProjectNamewraps fragmentreadFile+yaml.loadin one try/catch that ignores every failure (dockerCompose.ts 663-673); the prior commit propagated non-missing read errors asFilesystemError, which would fail the whole devcontainer flow for fragments the CLI would have silently skipped. Switches the loop to log + continue on anyfs.loadfailure. The stricter.envpolicy stays — it mirrors a separate, narrower CLI branch.Commits 1–2, 3–4, and 7–8 each follow a TDD RED/GREEN pattern; each RED/GREEN commit message captures the transition output.
Release Notes:
getProjectNameprecedence from the reference devcontainer CLI (COMPOSE_PROJECT_NAMEin the environment, then in the workspace.env, then an explicit top-levelname:on the merged compose config, then the basename of the first compose file's directory — with the_devcontainersuffix only when that directory is<workspace>/.devcontainer). This prevents duplicate containers when the same folder is opened with both Zed and the devcontainer CLI / VS Code, or with both new Zed and older Zed (≤v0.231.x) that shelled out to the CLI. On first run after the fix, if both a legacy-named and a CLI-style container exist, Zed now reuses the canonical one and logs the orphan instead of erroring.