Replaces a bunch of `impl FnMut` parameters with `&mut dyn FnMut` for
functions where this is the sole generic parameter.
Release Notes:
- N/A *or* Added/Fixed/Improved ...
Fixes#28339
## What
- Normalize cwd-relative path-like targets that include leading `..`
before worktree lookup.
- Update issue #28339 tests to expect `WorktreeExact` for local and
remote resolution.
## Why
- Prevent terminal links like `../foo/bar.txt` from creating invalid
entries; resolve to the correct worktree file instead.
## How to test
- `cargo test -p terminal_view issue_28339 -- --nocapture`
- Manual: open a workspace, run `echo ../foo/bar.txt` from a subdir in
the terminal, then cmd/ctrl-click and confirm the correct file opens.
## Risk
- Low: only changes terminal path-like resolution for `..` paths;
expected to match normalized behavior.
## Checklist
- [x] Tests run (`cargo test -p terminal_view issue_28339 --
--nocapture`)
- [x] Docs updated (not needed)
- [x] Backwards compatibility considered
Release Notes:
- Fixed an issue where relative paths starting with `..` would not resolve correctly when clicking the link in the terminal
---------
Co-authored-by: Ben Kunkle <ben.kunkle@gmail.com>
Replace `FuturesUnordered` with `FuturesOrdered` to maintain terminal
tab ordering when restoring a workspace.
Also clamp `pinned_count` to `items_len()` to prevent panics when fewer
terminals are restored than expected.
The changes:
1. Order preservation: `FuturesUnordered` → `FuturesOrdered` ensures
terminals restore in their original order
2. Bounds fix: `.min(pane.items_len())` prevents setting pinned count
higher than actual items
Closes#44463
Release Notes:
- Preserved terminal order and fixed pinned count on workspace restore
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
- Fix panics caused by reusing cached matches for the wrong side
- Highlight matches on the side that was searched only
- Clear matches in non-searched editor when initiating a new search
Release Notes:
- N/A
---------
Co-authored-by: Eric <eric@zed.dev>
Co-authored-by: Jakub <jakub@zed.dev>
- **build: remove assistant_slash_commands dependency in
assistant_text_thread**
- **diagnostics: Do not depend on search**
- **Remove terminal_view's dependency on search**
- **sever breadcrumbs <-> editor dep (for the sake of terminal_view)**
Release Notes:
- N/A
Currently we always compute breadcrumbs and sticky headers on every
editor paint which is not cheap to do especially in bigger files, moving
this off to be computed on event handling where they change and then
caching them can save serveral milliseconds per render in bigger files.
This also puts matching brackets refreshing and document highlights on a
background task, as this tends to block the main task for prolonged time
as well.
Release Notes:
- N/A *or* Added/Fixed/Improved ...
Closes#14863
Changes:
- Added `CurrentFileDirectory` variant to the `WorkingDirectory` enum.
- New terminals now open in the directory of the currently active file
when this option is set.
- Falls back to project directory, then first workspace directory if no
file is active.
Release Notes:
- Added `current_file_directory` option for terminal's
`working_directory` setting. Set `"working_directory":
current_file_directory"` to open new terminals in the directory of your
currently open file.
---
Still relatively new to Rust, so happy to receive any feedback! 😁
Summary
This PR adds the ability to quote terminal selections into Agent
threads, similar to how editor selections can be quoted. Users can now
select text in the terminal and add it as context to their agent
conversation.
### Features
- **Context menu**: Added "Add to Agent Thread" option to the terminal's
right-click menu (only shows when text is selected)
- **Keyboard shortcut**: The existing `cmd->` / `ctrl->` shortcut now
works in the terminal
- **Collapsed display**: Terminal output appears as a collapsed
"Terminal" crease in the chat, just like code references
- **Works with both thread types**: Supports both ACP-style threads
(Claude Code) and text threads
### Implementation
- Extended `quote_selection` handler to check for terminal panel focus
after checking for editor selections
- Terminal content is formatted as ` ```terminal` code blocks via new
`insert_terminal_crease` method
- Refactored crease insertion into `insert_crease_impl` helper to
support both code snippets (with `TextSnippet` icon) and terminal output
(with `Terminal` icon)
- Added automatic detection and folding of ` ```terminal` blocks in
`set_message` so terminal content stays collapsed in sent message
history
- Terminal creases use a trailing space instead of newline so cursor
behavior matches user expectations
### Demo
1. Select text in terminal
2. Right-click → "Add to Agent Thread" (or press `cmd->`)
3. Terminal content appears as collapsed "Terminal" block in chat
4. Send message - AI receives full terminal output, but chat history
shows it collapsed
### General note
I'm new to open source and the codebase in general so let me know if
anything should be different!
I tried to stay in line with other patterns I saw.
I didn't see a way to setup an end to end test with a real terminal so I
just added a unit test for the adding of the text to the chat, if it
exists and I missed it then I think the test coverage could be improved
with a test that uses a real terminal + running the command
<img width="431" height="148" alt="image"
src="https://github.com/user-attachments/assets/854732f9-2a7f-4f31-867e-d54af068c97c"
/>
Release Notes:
- agent: Added the ability to send selections from terminals into the
Agent thread
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
## Summary
This PR extends the `always_allow` tool permission patterns to work with
Nushell, Elvish, and Rc shells. Previously, these shells were
incorrectly excluded because they don't use `&&`/`||` operators for
command chaining. However, brush-parser can safely parse their command
syntax since they all use `;` for sequential execution.
## Changes
- Add `ShellKind::Nushell`, `ShellKind::Elvish`, and `ShellKind::Rc` to
`supports_posix_chaining()`
- Split `ShellKind::Unknown` into `ShellKind::UnknownWindows` and
`ShellKind::UnknownUnix` to preserve platform-specific fallback behavior
while still denying `always_allow` patterns for unrecognized shells
- Add comprehensive tests for the new shell support
- Clarify documentation about shell compatibility
## Shell Notes
- **Nushell**: Uses `;` for sequential execution. The `and`/`or`
keywords are boolean operators on values, not command chaining.
- **Elvish**: Uses `;` to separate pipelines. Does not have `&&` or `||`
operators. Its `and`/`or` are special commands operating on values.
- **Rc (Plan 9)**: Uses `;` for sequential execution and `|` for piping.
Does not have `&&`/`||` operators.
## Security
Unknown shells still return `false` from `supports_posix_chaining()`, so
`always_allow` patterns are denied for safety when we can't verify the
shell's syntax.
(No release notes because granular tool permissions are still
feature-flagged.)
Release Notes:
- N/A
---------
Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
We might interface with the LSP using URL heres across remotes that have
differing path styles which then breaks every now and then when we have
windows to unix connections. This should helps us fix these occurences
more correctly
Release Notes:
- N/A *or* Added/Fixed/Improved ...
Closes #ISSUE
Moves the settings content definitions into their own crate, so that
they are compiled+cached separately from settings, primarily to avoid
recompiles due to changes in gpui. In that vain many gpui types such as
font weight/features, and `SharedString` were replaced in the content
crate, either with `*Content` types for font/modifier things, or
`String`/`Arc<str>` for `SharedString`. To make the conversions easy a
new trait method in the settings crate named `IntoGpui::into_gpui`
allows for `into()` like conversions to the gpui types in
`from_settings` impls.
Release Notes:
- N/A
---------
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
The cursor in terminal vi mode was not visually updating when using
vi motion navigation keys, despite internal position tracking working correctly.
This was caused by missing `cx.notify()` calls to trigger re-rendering.
Refactored keystroke handling by extracting common logic from `key_down`
and `send_keystroke` into a shared `process_keystroke` helper method.
Closes#46736
Release Notes:
- terminal: Fixed vi mode cursor not visually updating when navigating
with vi motion keys
---------
Co-authored-by: dino <dinojoaocosta@gmail.com>
This PR adds the ability to open local terminals when working in remote
projects. When working in a remote (often actually remoting into a local
container) I always need to run separate terminals outside Zed so I can
run local build tools, scripts, agents, etc. for the related project.
I'd like to be able to run all of these in the same Zed window and this
adds that ability via one-off local terminals.
## Changes
Adds an optional `local` parameter to terminal commands. When set to
`true`, creates a local shell on your machine instead of connecting to
the remote.
### Implementation
- Added `force_local` parameter to terminal creation logic
- Created `create_local_terminal()` method that bypasses remote client
- Updated terminal actions (`NewTerminal`, `NewCenterTerminal`) to
accept optional `local: bool` field (defaults to `false`)
### Usage
**Via keybinding:**
```json
{
"bindings": {
"cmd-t": "workspace::NewCenterTerminal",
"cmd-T": ["workspace::NewCenterTerminal", { "local": true }]
}
},
{
"context": "Terminal",
"bindings": {
"cmd-n": "workspace::NewTerminal",
"cmd-N": ["workspace::NewTerminal", { "local": true }],
},
},
```
**Behavior:**
- Default terminal commands continue to work as before (remote in remote
projects, local in local projects)
- The `local` parameter is optional and defaults to `false`
Release Notes:
- Added support for opening local terminals in remote projects via
`local` parameter on terminal commands.
Closes#46574
The `default_working_directory()` function in
`crates/terminal_view/src/terminal_view.rs:1585` returned `None` when no
project directory was available. The code comment (now removed)
incorrectly claimed "None implies `~` on whichever machine we end up
on". However, when `None` is passed to `alacritty_terminal`, it uses the
process CWD, not the home directory. On macOS when Zed is launched from
a .`app` bundle, the CWD is `/`.
Added a fallback at the end of` default_working_directory()` that
explicitly returns the home directory when no project directory is
found: `directory.or_else(dirs::home_dir)`
This ensures:
1. `CurrentProjectDirectory` with no project open → home directory
2. `FirstProjectDirectory `with no project open → home directory
3. `AlwaysHome `→ home directory (explicitly, not relying on shell
behavior)
4. Always `{ directory }` with invalid directory → home directory
Release Notes:
- Fixed terminal opening in `/` instead of home directory when no
project is open.
Closes https://github.com/zed-industries/zed/issues/45553
## Summary
When using applications that hide the terminal cursor (e.g., via ANSI
escape sequence `\e[?25l`), the IME candidate window appeared at the
bottom-left of the screen, and the composition text was not displayed at
all. This affects tools like Claude Code that hide the cursor during
operation.
The root cause was that cursor position calculation was skipped when the
cursor shape was `Hidden`. This fix separates cursor visibility from IME
position calculation by always computing cursor bounds for IME
positioning.
## Movies
### Zed 0.218.6
https://github.com/user-attachments/assets/a66d569a-178d-4bca-a577-fcc65e9fd2c4
### With this fix
https://github.com/user-attachments/assets/456323d1-6c18-45ea-88e8-fb5375c00f98
Release Notes:
- Fixed IME candidate window and composition text position in terminal
when cursor is hidden
This brings the terminal element's viewport culling in line with the
editor optimization in PR #44995 and the fix in PR #45077.
## Problem
When a terminal is inside a scrollable container (e.g., the Agent Panel
thread view), it would render ALL cells during prepaint, even when the
terminal was entirely outside the viewport. This caused unnecessary CPU
usage when multiple terminal tool outputs existed in the Agent Panel.
## Solution
Calculate the intersection of the terminal's bounds with the current
content_mask (the visible viewport after all parent clipping). If the
intersection has zero area, skip all cell processing entirely.
### Three code paths
1. **Offscreen** (`intersection.size <= 0`): Early exit, process 0 cells
2. **Fully visible** (`intersection == bounds`): Fast path, stream cells
directly (no allocation)
3. **Partially clipped**: Group cells by line, skip/take visible rows
only
### Key insight: filter by screen position, not buffer coordinates
The previous approach tried to filter cells by `cell.point.line`
(terminal buffer coordinates), which breaks in Scrollable mode where
cells can have negative line numbers for scrollback history.
The new approach filters by **screen position** using
`chunk_by(line).skip(N).take(M)`, which works regardless of the actual
line numbers because we're filtering on enumerated line group index.
## Testing
Added comprehensive unit tests for:
- Screen-position filtering with positive lines (Inline mode)
- Screen-position filtering with negative lines (Scrollable mode with
scrollback)
- Edge cases (skip all, positioning math)
- Unified filtering works for both modes
Manually verified:
- Terminal fully visible (no clipping) ✓
- Terminal clipped from top/bottom ✓
- Terminal completely outside viewport ✓
- Scrollable terminals with scrollback history ✓
- Selection/interaction still works ✓
Release Notes:
- Improved Agent Panel performance when terminals are scrolled
offscreen.
/cc @as-cii
Draft as a base for continuing the discussion in #8008 : adds a
`SplitOperation` enum to support bindings like `["pane::SplitLeft",
{"operation": "Clear"}]`
To be discussed @MrSubidubi and others:
- Naming: Generally not happy with names yet and specifically `Empty` is
unclear, e.g., what does this mean for terminal panes? Added placeholder
code to split without cloning, but unsure what users would expect in
this case.
- ~~I removed `SplitAndMoveXyz` actions but I guess we should keep them
for backwards compatibility?~~
- May have missed details in the move implementation. Will check the
code again for opportunities to refactor more code after we agree on the
approach.
- ~~Tests should go to `crates/collab/src/tests/integration_tests.rs`?~~
Closes#8008
Release Notes:
- Add `pane::Split` mode (`{ClonePane,EmptyPane,MovePane}`) to allow
creating an empty buffer.
---------
Co-authored-by: Finn Evers <finn.evers@outlook.de>
Co-authored-by: MrSubidubi <finn@zed.dev>
Closes https://github.com/zed-industries/zed/issues/43208
This PR essentially unblocks the editable number field. The function
that shapes editor lines was hard-coding text alignment to the left,
meaning that whatever different alignment we'd pass through
`EditorStyles`would be ignored. To solve this, I just added a text align
and align width fields to the line paint function and updated all call
sites keeping the default configuration. Had to also add an
`alignment_offset()` helper to make sure the cursor positioning, the
selection background element, and the click-to-focus functionality were
kept in-sync with the non-left aligned editor.
Then... the big star of the show here is being able to add the `mode`
method to the number field, which uses `TextAlign::Center`, thus making
it work as we designed it to work.
https://github.com/user-attachments/assets/3539c976-d7bf-4d94-8188-a14328f94fbf
Next up, is turning the number filed to edit mode where applicable.
Release Notes:
- Fixed a bug where different text alignment configurations (i.e.,
center and right-aligned) wouldn't take effect in editors.
## Summary
Fixes arithmetic underflow panics in `terminal_scrollbar.rs` by
converting unsafe subtractions to `saturating_sub`.
Closes#45281
## Problem
Two locations perform raw subtraction on `usize` values that panic when
underflow occurs:
- `offset()`: `state.total_lines - state.viewport_lines -
state.display_offset`
- `set_offset()`: `state.total_lines - state.viewport_lines`
This happens when `total_lines < viewport_lines + display_offset`, which
can occur during terminal creation, with small window sizes, or when
display state becomes stale.
## Solution
Replace the two unsafe subtractions with `saturating_sub`, which returns
0 on underflow instead of panicking.
Also standardizes the existing `checked_sub().unwrap_or(0)` in
`max_offset()` to `saturating_sub` for consistency across the file.
## Changes
- N/A
## Summary
Fix panic "cannot update workspace::pane::Pane while it is already being
updated" when dragging terminal tabs to split the pane.
## Problem
When dragging a terminal tab to create a split, the app panics due to
re-entrancy: the drop handler calls `terminal_panel.center.split()`
synchronously, which invokes `mark_positions()` that tries to update all
panes in the group. When the pane being updated is part of the terminal
panel's center group, this causes a re-entrancy panic.
## Solution
Defer the split operation using `cx.spawn_in()`, similar to how
`move_item` was already deferred in the same handler. This ensures the
split (and subsequent `mark_positions()` call) runs after the current
pane update completes.
## Test plan
- Open terminal panel
- Create a terminal tab
- Drag the terminal tab to split the pane
- Verify no panic occurs and split works correctly
Closes#45179
## Summary
Fixes the focus behavior when creating terminals with
`RevealStrategy::NoFocus` or `RevealStrategy::Never`. Previously,
terminals would still receive focus if the terminal pane already had
focus, contradicting the documented behavior.
## Changes
- **`add_terminal_task()`**: Changed focus logic to only focus when
`RevealStrategy::Always`
- **`add_terminal_shell()`**: Same fix
The fix changes:
```rust
// Before
let focus = pane.has_focus(window, cx)
|| matches!(reveal_strategy, RevealStrategy::Always);
// After
let focus = matches!(reveal_strategy, RevealStrategy::Always);
```
## Impact
This affects:
- Vim users running `:!command` (uses `NoFocus`)
- Debugger terminal spawning (uses `NoFocus`)
- Any programmatic terminal creation requesting background behavior
Release Notes:
- Fixed terminal focus behavior to respect `RevealStrategy::NoFocus` and
`RevealStrategy::Never` settings when the terminal pane already has
focus.
When running Codex CLI, Claude Code, or other TUI agents in Zed’s
terminal, pasting images wasn’t supported — Zed
treated all clipboard content as plain text and simply pushed it into
the PTY, so the agent never saw the image data.
This change makes terminal pastes behave like they do in a native
terminal: if the clipboard contains an image, Zed now emits a raw Ctrl+V
to the PTY so the agent can read the system clipboard itself.
Release Notes:
- Fixed terminal-launched Codex/Claude sessions by forwarding Ctrl+V for
clipboard images so agents can attach them
Closes #ISSUE
Problem:
- The status bar’s pending keystroke indicator (shown next to --NORMAL--
in Vim mode) didn’t clear when focus moved to another context, e.g.
hitting g in the editor then clicking the Git panel. The keymap state
correctly canceled the prefix, but observers that render the indicator
never received a “pending input changed” notification, so the UI kept
showing stale prefixes until a new keystroke occurred.
Fix:
- The change introduces a `pending_input_changed_queued` flag and a new
helper `notify_pending_input_if_needed` which will flushes the queued
notification as soon as we have an App context. The
`pending_input_changed` now resets the flag after notifying subscribers.
Before:
https://github.com/user-attachments/assets/7bec4c34-acbf-42bd-b0d1-88df5ff099aa
After:
https://github.com/user-attachments/assets/2264dc93-3405-4d63-ad8f-50ada6733ae7
Release Notes:
- Fixed: pending keybinding prefixes on the status bar now clear
immediately when focus moves to another panel or UI context.
---------
Co-authored-by: Nathan Sobo <nathan@zed.dev>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
🔜
TODO:
- [x] Add a utility pane to the left and right edges of the workspace
- [x] Add a maximize button to the left and right side of the pane
- [x] Add a new agents pane
- [x] Add a feature flag turning these off
POV: You're working agentically
<img width="354" height="606" alt="Screenshot 2025-12-13 at 11 50 14 PM"
src="https://github.com/user-attachments/assets/ce5469f9-adc2-47f5-a978-a48bf992f5f7"
/>
Release Notes:
- N/A
---------
Co-authored-by: Nathan Sobo <nathan@zed.dev>
Co-authored-by: Zed <zed@zed.dev>
This ensures that the casing of this entry aligns with other entries in
the app popover Menus.
Release Notes:
- N/A
---------
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Just recently realized we don't need this custom component for it given
we now have `Tooltip::element`. UI result is exactly the same; nothing
changes.
Release Notes:
- N/A
Fixes an issue where the terminal cursor wouldn't always be displayed in
the default `blink: "terminal_controlled"` mode unless the terminal
requested cursor blinking.
Release Notes:
- N/A
Fixes#42945
## Problem
When opening a single file via command line (e.g., `zed
~/Downloads/file.txt`), the terminal panel was opening in the root
directory (/) instead of the file's directory.
## Root Cause
The code only checked for active project directory, which returns None
when a single file is opened. Additionally, file worktrees weren't
handling parent directory lookup.
## Solution
Added fallback logic to use the first project directory when there's no
active entry, and made file worktrees return their parent directory
instead of None.
## Testing
- All existing tests pass
- Added test coverage for file worktree scenarios
- Manually tested with `zed ~/Downloads/file.txt` - terminal now opens
in correct directory
This improves the user experience for users who frequently open single
files from the command line.
## Release Notes
- Fixed terminal opening in root directory when editing single files
from the command line