While the debugger is suspended, hovering the start of a line shows a small
button left of its text: Run to Cursor runs to that line, and on the execution
line it resumes the program. Settings › Debugger › Show inlay Run to Cursor popup
turns it off.
The project view context menu gains Jump to Source (F4) for files. Recent Files
no longer lists files deleted since they were opened, including files removed
while the IDE was closed; virtual documents stay listed.
Pressing Enter in Recent Files when the filter matches nothing now opens Go to
File with the typed text, so the search carries on over the whole project.
The editor tab menu gains Close All Read-Only Tabs (shown when the group has
unpinned read-only tabs) and Keep Tab Open (on a preview tab), which turns the
preview into a regular tab.
Adds three split actions to the editor tab menu, the Window › Editor Tabs menu and
Find Action: Open in Opposite Group keeps the tab and opens a copy in the
neighbouring group (splitting when there is none), Change Splitter Orientation
flips the split holding the current group, and Unsplit All closes every other
group.
Page Down / Page Up and ⌘↓ / ⌘↑ (Ctrl+Down / Ctrl+Up on Windows) move the
selection to the first result of the next or previous group (Classes,
Files, Symbols, Actions…), including in the All tab, where groups have no
header rows. ⌘↑ inside a popup no longer jumps to the navigation bar.
- Debug console: typed expressions are kept per project, and Browse Console
History (⌥⌘E / Ctrl+Alt+E) lists them, most recent first, to put one back
into the input.
- Diff viewer: Diff Settings (⇧⌘D / Ctrl+Shift+D) opens the viewer options
(side-by-side / unified, whitespace, highlighting, collapsing, scroll sync)
as a popup menu.
View > Context Info (Ctrl+Shift+Q on macOS, Alt+Q on Windows) shows the
class, method and block header lines around the caret in a hint, which helps
when they are scrolled out of view.
- Accept Left Side / Accept Right Side copy the change at the caret to the
other side of a side-by-side diff (⌃⌘→ / ⌃⌘← on macOS, Ctrl+Alt+R /
Ctrl+Alt+A on Windows).
- Compare Next File / Compare Previous File open the neighbouring file of
the diff chain directly (⌃⇧→ / ⌃⇧← on macOS, Alt+Shift+→ / ← on Windows).
The Services tool window lists run configurations next to Docker. Spring Boot configurations appear by default; other types (Application, npm, Maven, Gradle, …) are added with + › Run Configuration Type and removed with Remove from Services, remembered per project. Nodes group by type and show running / stopped, with Run / Rerun, Debug, Stop, Show in Run Tool Window and Edit Configuration… in the toolbar and context menu; the detail pane shows the same console as the Run tool window. Running Spring Boot apps show the HTTP port read from the embedded server's "started on port" line.
Rerun now waits for the old process to exit before starting the new one, so a restarted server no longer fails with its port already in use, and a process stopped by the user no longer raises an exit-code notification.
Closes#150
Claude-Session: https://claude.ai/code/session_01Dq6jQQn8ZhRfkkyj3PRutA
The main Log tab opened with no branch filter and showed all branches. It now starts on HEAD (Current Branch), which follows checkouts, and a branch filter the user picks (including multi-selection and all branches) is remembered per repository across restarts, stored with the other per-repository Git UI state. Remembered refs that no longer exist are dropped, falling back to HEAD when none are left. Also fixes the first checkout or commit after opening the Log not refreshing it.
Claude-Session: https://claude.ai/code/session_01Dq6jQQn8ZhRfkkyj3PRutA
Co-authored-by: itning <19759891+itning@users.noreply.github.com>
Files opened from inside the app (File › Open File…, a drop on the Welcome screen, Open File in a single-file window) were always kept in the requesting window, so a file belonging to a project open in another window went to the single-file window instead. These paths now follow the same rule as Finder, Dock and second-instance opens: window_open_files normalises the paths and routes them through plan_open via plan_open_files, which sends files inside an open local project to that project's window. It returns only the files the requesting window should open itself. The TypeScript side no longer has any routing logic. Files dropped onto a project window still open in that window.
Refs #128
Editing and folding
- Move Caret to Code Block Start / End with Selection, Auto-Indent Lines,
Move Element Left / Right (swaps call arguments, parameters and list
entries).
- Fold Code Block folds the {...} block around the caret; Expand to Level
and Expand All to Level 1-5.
- Custom folding regions (//region, #region, <editor-fold>) fold to their
description; Navigate > Custom Folding lists them.
- Error Description shows the problems at the caret; Next / Previous
Highlighted Usage steps through usage highlights.
- Editor tooltips stay below the editor's top edge, so hints on the first
lines no longer hide under the tab bar.
Navigation, project and run
- Navigate > File Path lists the file and its folders to reveal in the file
manager.
- Copy... (F5) opens the Copy dialog for the selection or the open file; the
project view's Refactor submenu gets Copy File.
- Debug... chooses a configuration to debug; Quick Evaluate Expression shows
the selection's value in an expandable hint.
- Inspect Current File runs the inspection without the scope dialog.
- Surround with Live Template lists only $SELECTION$ templates; Java gets
Callable, read / write lock and iterate templates.
Windows
- Stretch the active tool window left / right / up / down, Restore Default
Layout, Go to Next / Previous Splitter, Close Active Tab on a second key,
Stop Background Processes.
All actions have default shortcuts in both keymaps, VS Code preset entries,
main menu items and Chinese translations.
Project view and Keymap settings
- Project view Options: Sort by Name / Type / Modification Time (also in
Find Action).
- Settings > Keymap: Add Mouse Shortcut records a side-button click with
modifiers and checks conflicts like keyboard shortcuts.
- Folding: Expand to Level / Expand All to Level 1-5.
Semantic token decorations were registered at Prec.high, the same precedence as CodeMirror's tree highlighter, so the syntax span ended up innermost and its colour won over the semantic one (fields, constants and other LSP-coloured identifiers looked like plain text). They now register at Prec.highest. The ⌘-hover link colour is kept over semantic colours, and semantic modifier lookup ignores Object.prototype names, which turned jdtls' `constructor` modifier into a bogus class.
Claude-Session: https://claude.ai/code/session_01Dq6jQQn8ZhRfkkyj3PRutA
Co-authored-by: itning <19759891+itning@users.noreply.github.com>
Run configuration detection only looked for pom.xml / build.gradle(.kts) at the opened root, so a Maven or Gradle build in a subfolder produced no configurations, and Java files fell back to a single-file `java X.java` launch without classpath or build. Detection now takes the root build, or else the shallowest build on each branch up to three levels down, with the subfolder in the config's cwd, id and name; a multi-module parent pom counts as one build. Spring Boot applications (@SpringBootApplication with main in a module that applies the Spring Boot plugin) get spring-boot configurations that build the module and run with its classpath. Gutter and file runs pick the build the file belongs to (also for Go modules), and only files outside any build run as single files; the main config lookup takes the nearest bootRun / run / spring-boot:run.
On Windows, piped JVM (java, Maven, Gradle) and Python processes now write in the console encoding instead of the ANSI code page, so their output is no longer garbled. run_configs runs on a blocking thread.
Fixes#149
Claude-Session: https://claude.ai/code/session_01Dq6jQQn8ZhRfkkyj3PRutA
Find in the diff viewer (⌘F / ⌘R / ⌘G) opens the editor's find bar instead of CodeMirror's search panel: same field, Match Case / Words / Regex, counter, navigation, filter menu and highlights. In the side-by-side viewer the bar sits over the side with the caret, Replace is offered only on editable sides, and the shortcuts come from the keymap. Esc closes the bar even while a match is selected.
Claude-Session: https://claude.ai/code/session_01Dq6jQQn8ZhRfkkyj3PRutA
Co-authored-by: jaw52 <53564781+jaw52@users.noreply.github.com>
ngserver (@angular/language-server) runs next to vtsls and the HTML server in Angular projects, bringing completion, hover, definition, diagnostics, references and rename to external and inline component templates. A language server can now require a root marker (require-root-marker), so the Angular server only serves files below angular.json or node_modules/@angular/core and never hides the typescript-language-server fallback elsewhere. Attached servers keep definition order, and rename merges the edits of every server that accepts the position. Installable from the tools registry via npm.
Claude-Session: https://claude.ai/code/session_01Dq6jQQn8ZhRfkkyj3PRutA
Co-authored-by: nntndfrk <2458463+nntndfrk@users.noreply.github.com>
Settings › Editor › General › Appearance gets "Use smooth caret blinking" and "Use smooth caret movement" (Snappy / Gliding), both off by default. Smooth movement animates only navigation and clicks; typing, edits and scrolling moves stay instant, and reduced motion turns it off. The diff and merge viewers now use the editor's caret and follow these settings instead of CodeMirror's default caret. Also translates a select's value shown while its checkbox is unchecked.
Claude-Session: https://claude.ai/code/session_01Dq6jQQn8ZhRfkkyj3PRutA
Co-authored-by: jaw52 <53564781+jaw52@users.noreply.github.com>
Result lines in the Find in Files popup and tool window and in the Show Usages popup and Usages tool window are coloured like the editor, using the whole file as context, so a line inside a block comment or a multi-line string gets the right colour. The colouring lives in editor/lineTokens and all four lists share it; each file is parsed once and cached, and the parse runs in 8 ms time slices so large files don't block the UI thread. Lines that moved since the search, and files over 500k characters, are coloured on their own.
Claude-Session: https://claude.ai/code/session_01Dq6jQQn8ZhRfkkyj3PRutA
Co-authored-by: jaw52 <53564781+jaw52@users.noreply.github.com>
On macOS, OpenIDEA is now listed under Finder's Open With for text and source files and for folders. It never becomes the default app for any of them: all document types are declared with rank Alternate, and only in tauri.macos.conf.json, so Windows and Linux installers register nothing.
Files opened from Finder, the Dock or a second instance share one routing path (plan_open). A file inside a local project that is already open, or still opening, goes to that project's window, choosing the deepest root when projects are nested. Any other file goes to the existing single-file window, or to a new one. A folder focuses the window that already has it open, otherwise it opens as a project. Paths that arrive before setup are queued and opened with the first launch.
The single-file window now closes with its last tab, restores its files the next time it opens, and only offers Open File and drop hints when empty. Also fixes a regression: reopening projects on startup no longer replaces a file opened at cold start.
Refs #128
Files can now be opened without a project. A file dropped on the Welcome screen, picked with File › Open File…, or passed on the command line or to a second instance opens in a lightweight window: editor tabs only, with no project tree, indexing, language servers, VCS or project tool windows. Syntax highlighting, find, save, undo and Local History still work. More files opened later join the same window as new tabs. Open as Project in the status bar opens the file's directory as a full project, following the open-project policy, and reopens the file there.
Backend: a light session reuses Project with an unindexed index, no LSP or VCS, and a flat watch on each opened file's directory. It is never reused as a project for the same root. Previously a file passed at launch opened its parent directory as a project.
- Settings › Commit › "Use non-modal commit interface": when off, Local
Changes, Shelf and Stash become tabs of the Git tool window and ⌘K opens
a Commit dialog; switches live.
- Git tool window: Worktrees tab; Show History and Show Git Log for a
branch open their own closable tabs instead of changing the Log filters.
- Log: toolbar and context menu for a commit's changed files, vertical
toolbar, Tags node and hiding for the branches pane, Collapse / Expand
Linear Branches as separate actions, and a Version Control › Log page.
- Branch popup: collapsible groups, branches grouped by prefix, an options
menu behind the gear, incoming / outgoing icons and "Pull into … Using
Rebase / Merge"; New Branch on ⌥⌘N outside the editor.
- Git main menu regrouped with Uncommitted Changes and Current File
submenus; rebase / merge controls enabled only while one is in progress.
- Settings: Version Control lists its pages; new options for clearing the
initial commit message, showing Update options, confirming dropped
commits, revealing created patches, large-file and file-name warnings,
the Push dialog after Commit and Push, combined stashes and shelves, and
removing applied files from the shelf.
Root cause: once a project was open, nothing outside the Project view handled files dropped from the OS, so drops onto the editor, tabs or other tool windows were ignored.
A window-wide handler now opens dropped files in the editor (one tab each, last one focused, files outside the project included) and opens a dropped folder as a project through the open-project policy. Regions that handle drops themselves (Project view, agent prompt box) are marked with OWNS_FILE_DROP and hit-tested, so each drop has a single handler; the Welcome screen and remote windows are left alone.
* fix(terminal): Line height, colour palette and tab names
- Line height: with "Use editor font" the terminal took the editor's roomier
line height (about 1.33 cells), stretching ASCII art and box drawing. It now
always uses Settings › Tools › Terminal › Line height (default 1.0); that
field moves out of the "Use editor font" group since it applies either way.
- Colours: the terminal gets its own --terminal-ansi-* palette (the light and
Darcula terminal colours); the Run console keeps --ansi-*. High-contrast and
palette themes keep their console colours. Colours below a 4.5:1 contrast
with the background are adjusted (xterm's minimumContrastRatio), so yellow
stays readable on white.
- Tab names: tabs keep their default name ("Local", "Local (2)") at the prompt
and show the title a program sets only while a command runs. Shell
integration now marks command start and end (OSC 133 C / D) for zsh,
bash 4.4+ (PS0) and fish.
* fix(themes): Document the terminal ANSI palette for theme plugins
The --terminal-ansi-* tokens belong in a theme's editor colour scheme, like
--ansi-*. The theme plugin template sets them and the token reference lists them.
Switching between agent session tabs in the editor now moves the Agents
tool window's selection to that task, expanding its group (e.g. Archived)
when it is collapsed. The list also opens with the active session selected.
Tabs of other kinds leave the selection as it is.
The editor service gains activeInput() and onActiveInputChange() so
features can follow the active tab of any kind.
Run oxfmt once over the whole repository (formatting only, no logic changes) and add `pnpm format:check` to the frontend CI job so unformatted code no longer builds up. `.oxfmtrc.json` now skips the generated theme docs, test fixtures and code blocks inside Markdown.
Co-authored-by: jaw52 <53564781+jaw52@users.noreply.github.com>
The Branch filter in the Git log opens a popup with a search field instead of a plain menu. Branches are fuzzy-matched with highlights and grouped under HEAD, Local and Remote; arrow keys skip the group headers and Enter applies the filter. The list is virtualized so large repositories stay responsive, and Select… still opens the multi-branch / custom revision chooser.
Co-authored-by: zzxzz12345 <8338183+zzxzz12345@users.noreply.github.com>
Dragging the bottom tool window edge over a terminal refit xterm on every
pointer move and sent each intermediate size to the shell, which redrew its
prompt every time. Terminals now refit at most every 100 ms while their host
keeps resizing, plus once when it stops, and the process only learns the size
once it has held for 150 ms. This covers the Terminal tool window and terminals
embedded in Run consoles.
Resizing the width of an agent conversation reflowed every entry, including the
off-screen ones (14-16 ms per move in a long session). Entries now use
content-visibility: auto, so only the visible ones are laid out.
Code previews (Find in Files, Usages) are non-editable CodeMirror views, so their text inherited the workbench's user-select: none and had no tab stop: it couldn't be focused, selected with the keyboard or copied. Previews now opt their content back in with the shared selectable-text class and take a tab stop; editing stays blocked. Same root cause as the read-only diff panes (#126).
Read-only revision panes inherited the workbench's user-select: none and had no tab stop, so text couldn't be selected with the mouse or keyboard or copied. The viewer content now allows text selection and read-only panes take focus; editing stays blocked.
Once focusable, these panes picked up CodeMirror's dark-theme focused selection colour, which outranked the viewer's rule and made selected text unreadable in light themes; the viewer's selection rule now matches that specificity.
Co-authored-by: dvictor357 <187467850+dvictor357@users.noreply.github.com>
When a list item's text was followed by a nested list and a selection ended at
the end of that text, WebKit painted a thin strip of selection from there to the
right edge. The text of such items now gets its own block.
Dragging a tool window edge set an inherited custom property on the tool window
grid, so every pointer move restyled the whole workbench below it. With a long
agent conversation open each move cost 150-400 ms. The grid track variables are
now registered as non-inherited, and the side splitter sets flex-grow on its two
areas instead of inherited variables on the side.
* feat(agents): Show subagents as their own conversations
Agents that support ACP subagent sessions (Claude Code, Codex) now run each
subagent as a child session. Its tool calls and messages no longer mix into
the task's conversation: the parent shows a card per subagent with its state,
tool call count, latest step, task and result, and the card opens the
subagent's own conversation.
- Route session/update by session id; subagent settings and usage stay out
of the task.
- Subagent permission requests are answered in the task's conversation,
named after the subagent.
- Subagent conversations are saved with the task; a running subagent is
marked stopped after a restart.
- A running subagent can be stopped on its own.
* fix(agents): Save a subagent's state when it changes after the turn
Removing a language server (disabled in settings via stop_unlisted, or a fallback detached when its preferred server comes back) only emitted a stopped state, and the status bar list only refreshed for unknown servers, so the removed server stayed until the project was reopened. Both paths now go through forget(), which drops the server and emits IdeEvent::LanguageServerRemoved; the frontend drops the entry and ignores stale lsp_servers results that still contain it. Stopped servers no longer count towards "+N".
Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
ty (`ty server`) joins basedpyright and Pyright as a Python language server (fallback, gets the project venv like the others, installable from Tools). Settings › Language Servers gets a Python language server picker: Automatic (first available), basedpyright, Pyright, ty or None, written through the per-server enabled settings (null globally / true in a project for enabled, false for disabled); other combinations show as Custom combination. Picker text is translated; the hint sits on its own line.
Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Co-authored-by: zzxzz12345 <8338183+zzxzz12345@users.noreply.github.com>
* fix(agents): Leave changes made before a local checkout task out of its changes
A task in the project's own checkout listed every uncommitted and untracked
file as its own. The files already changed when the task starts are now
recorded with their size and modification time, and drop out of the task's
changes until they are edited again.
* feat(agents): Show the current branch for a local checkout task
* fix(app): Survive panics in background work and log them
A panic in background work (a spell check, an LSP handler) aborted the whole
app and left nothing behind: the message went to stderr, which a launched app
doesn't keep, and the stripped binary gave crash reports no function names.
- Release builds unwind, so a panic fails one task or command instead of
quitting the IDE. Commands already turn a panicked blocking task into an
error, and the existing catch_unwind around JSON-RPC notification handlers
now takes effect.
- A panic hook appends the thread, location, message and backtrace to the
log file synchronously, before the non-blocking writer could lose them.
- Release builds keep the symbol table (strip = "debuginfo"), so crash
reports and logged backtraces name functions.
* test(app): Match the panic location with file!() so the test passes on Windows
pnpm lint runs oxlint and pnpm format runs oxfmt: lint ~0.3s instead of ~20s, format check ~0.2s instead of ~11s, with far less memory. Configs come from the official migration tools (.oxlintrc.json from eslint.config.js, .oxfmtrc.json from the Prettier config); six new findings fixed or suppressed in 4 files. No code is reformatted.
Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Co-authored-by: jaw52 <53564781+jaw52@users.noreply.github.com>
known_run stepped one byte past the delimiter before a word run, which lands inside a multi-byte character (Chinese punctuation, emoji) and panics when slicing. It now steps past the whole character. Regression test with Chinese punctuation and emoji.
Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Co-authored-by: zzxzz12345 <8338183+zzxzz12345@users.noreply.github.com>
Fixes#117
Inside an AppImage, AppRun and the linuxdeploy GTK/GStreamer hooks point LD_LIBRARY_PATH, PATH, XDG_DATA_DIRS, GIO_MODULE_DIR, GTK_PATH, GST_PLUGIN_* … into the mounted image, and every child inherited them, so host programs loaded the image's older libraries (curl + bundled nghttp2 → symbol lookup error when installing Kotlin LSP). ide_core::process::prepare (formerly no_window) now gives children the host environment back: entries inside $APPDIR are dropped (a <NAME>_ORIG wins), emptied variables and the runtime's launch variables are removed, explicit call-site values are kept; the IDE process itself is unchanged. Covers all spawn sites that used no_window plus terminal/run PTYs, run configuration environments and stop commands, login-shell probes, attach ps/kill, docker PATH, tool search PATH and the Linux browser opener. No-op outside an AppImage. Not verified on a Linux AppImage.
Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Multi-repo branch popup matches actions by their translated label (highlights and Chinese search now work) and translates its group headers. Conflict counts, relative times (shared dateFormat), in-progress operation titles, git operation progress/results, branch widget tooltips, diff/hunk counts, worktree markers, PR author line and review placeholders go through tx; the default "Changes" changelist shows its translated name. HexViewer read-only leaves the untranslated allowlist. 92 zh entries.
Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Hard-coded UI text, titles and aria-labels in about 110 components (Git panels, hierarchy, pull requests, dialogs, settings, welcome) now go through tx; spliced fragments became whole sentences (fileCount, noneFoundLabel, hierarchyTitle) and pull request states use keyed messages. 225 zh entries added, stale fragment entries removed.
Also: tx used as a tag without interpolations (tx`No checks`) now looks the text up exactly instead of as a template, so it is translated like tx("No checks"); the text-catalog test checks such tags as plain literals. Check and test counts reuse the existing "{count} passed" / "{failed} failing" entries.
Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Co-authored-by: jaw52 <53564781+jaw52@users.noreply.github.com>
A local-checkout task shows the repository's current branch in its header, and
Changes compares against it; both follow branch switches. The header also shows
the time the agent has spent on the task's turns.
A usage update without a cost (Claude sends one for its rate limits) no longer
clears the session cost.
With a line height above 1, xterm's DOM renderer stretched the cursor cell
over the full row. Size it to the font's own height and centre it with the glyphs.