`taskkill /T /F` only starts terminating the tree, and the caller then
waits for its direct child. A grandchild could still be exiting, with its
files open, when `kill_tree` returned or `Peer::exited` resolved. The
descendants are now opened before the kill and waited for (up to 5 s)
after it. A process counts as a descendant only if it started after its
parent, so a reused parent id doesn't pull in unrelated processes.
Closes#1270
Finder/Dock-launched apps only got PATH from the login shell; children outside run configs, LSP and DAP missed rc exports such as GOMODCACHE, so go list showed only some modules. host_env now adds the shell's variables the process lacks (call-site values win); the login-shell probe leaves them out so Reload Environment stays accurate. Covers every crate that spawns through ide_core::process::prepare/host_env.
A task's agent process lived until the task was archived or the project closed, and stopping it killed only the direct child, so wrappers (npx, codex.cmd, claude shims) left the real agent running. Agents that support session/load are now stopped after 5 minutes idle and restarted with the session reloaded on the next message; agent connections, language servers and the native Claude CLI start in their own process group and are stopped with their whole tree.
New tasks run in the local checkout unless the user picks a worktree, and worktrees go next to the project (<parent>/<project>.worktrees/<task>), on the project's drive and outside its tree.
Fixes#1011Fixes#1003
Five crates (tools, build, vcs, github, docker) each carried their own copy of killing a child and what it started, and only the tools installer killed the whole tree on Windows, so cancelling git, gh, docker or Maven/Gradle there left descendants running. ide-core now provides own_group, kill_tree and terminate_tree (process-group signals on Unix, taskkill /T /F on Windows) and the copies are removed. Unix behaviour is unchanged; the Windows path was not run locally.
Co-authored-by: bograh <[email protected]>
* fix(core): read the Windows user PATH past REG_EXPAND_SZ quirks
`RegGetValueW` reports the unexpanded size of a `REG_EXPAND_SZ` value, so
a user `Path` that grows when its `%VAR%` references are expanded was
silently dropped. And when the terminating NUL leaked into the read
buffer with a stray UTF-16 unit behind it, `trim_end_matches('\0')`
left that unit in the string and `env::set_var("PATH", ...)` panicked
("strings passed to WinAPI cannot contain NULs", #683).
Re-read at the size the failed call reports, and cut the decoded string
at the first NUL instead of trimming trailing ones. Covered by a test
against a throwaway key under HKCU\Software.
* test: cover registry terminator corruption and refresh inspection groups
---------
Co-authored-by: l0ng-ai <[email protected]>
* fix(tools): include the Windows user PATH agents and tools are resolved on
On Windows the login-shell environment is never read (it is a Unix-only path),
so a process started before the user PATH was edited — or one that simply does
not inherit it — resolves agent executables and language-server tools on the
machine PATH alone. A tool installed for the user (npm -g, \dotnet tool
install -g\, a vendor installer) is then reported as not on PATH.
Read the user's own PATH from HKCU\\Environment (expanding REG_EXPAND_SZ
entries) and append its directories after the inherited ones in both the tool
search path and the native agent lookup, so user installs resolve without
shadowing the inherited order.
Fixes#330.
* fix(tools): use div_ceil for the registry buffer size
* fix(tools): add the Windows user PATH to the process PATH at startup
Lookups alone left agents reported as not installed, and programs started from
user PATH entries could not find their own dependencies.
---------
Co-authored-by: l0ng-ai <[email protected]>
On Windows std/tokio Command only tries .exe for a bare program name, so agents installed as npm shims (codex.cmd, claude.cmd) failed with "program not found". Bare names are now resolved through PATH x PATHEXT before spawning.
- ide-core::process gains find_executable / find_executable_in (moved from ide-run::which, which re-exports them).
- ide-jsonrpc Peer::spawn_framed resolves against the child's PATH (caller env, login shell, then ours): covers ACP agents and the native Codex driver.
- ide-agent newest_install builds candidates with executable_names, so the native Claude driver finds .cmd shims and multi-install selection works on Windows.
- ide-agent replay recorder resolves the same way.
Co-authored-by: a-rookie-of-C-language <[email protected]>
* feat(settings): HTTP Proxy settings for the IDE's outgoing connections
Add Appearance & Behavior › System Settings › HTTP Proxy with three modes:
No proxy, Auto-detect proxy settings (the default; environment proxy as
before) and Manual proxy configuration (HTTP or SOCKS, host and port, a
comma-separated "No proxy for" list with `*` wildcards, optional proxy
authentication). "Check connection…" GETs a URL with the settings as edited
and reports the status or the error.
- ide-core: `ProxySettings` plus routing (no-proxy globs, loopback always
direct, credentials percent-encoded), the current proxy for the process,
curl arguments and child-process variables.
- ide-http: `client::build` / `client::shared` is the one HTTP client
constructor; the HTTP Client requests and the update check go through it.
- ide-tools: curl downloads (tools, JDKs, debug adapters, agent registry,
remote server) follow the setting.
- A manual proxy reaches child processes (language servers, debug adapters,
terminals, git) as HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY.
- The proxy password is kept in the owner-only saved passwords file
(`proxy-password.json` in the app data directory), not in settings.toml.
Co-Authored-By: Claude <[email protected]>
* fix(host): Allow the Unix-only post-start test helpers on Windows
Co-Authored-By: Claude <[email protected]>
---------
Co-authored-by: Claude <[email protected]>
java-debug runs inside jdtls and is reached through its debugServer port, but configurations that aren't Application / Spring Boot and select java-debug (a Shell Script running `catalina.bat run`, say) fell through to the generic launch template, and the adapter launcher tried to start com.microsoft.java.debug.plugin.jar as a process: on Windows that failed with os error 193, elsewhere with a misleading "debug adapter not found".
- Shell script / program configurations with java-debug start with a suspended JDWP agent injected through JAVA_TOOL_OPTIONS and attach once the JVM prints its port, so `catalina.bat run` / `catalina.sh run` can be debugged.
- Maven goals that run the app in Maven's JVM (tomcat7:run, jetty:run(-war), exec:java, or any Maven config with java-debug) are debugged through MAVEN_OPTS.
- Gradle tasks that start no JVM say why they can't be debugged; `debug.startConfig` with a single debuggable config goes through the run debug flow.
- .jar adapters are never spawned as processes, and Windows adapter lookup only accepts PATHEXT files (so npm-installed adapters pick the .cmd shim instead of the POSIX one); the PATHEXT expansion moves to ide_core::process::executable_names, shared with ide-run.
Not run on Windows; the Windows resolution is covered by tests with an injected platform.
Fixes#179
Claude-Session: https://claude.ai/code/session_01Dq6jQQn8ZhRfkkyj3PRutA
The remote server read the login shell's PATH once and cached it, had no project-level environment, and changed environment variables only took effect after reinstalling or a manual restart.
- Every openidea-server start re-reads the remote login shell's full environment (`$SHELL -ilc env -0`), with the cached PATH only as a fallback when the shell doesn't answer.
- A project's `.devcontainer/devcontainer.json` (or `.devcontainer.json`) applies on remote hosts: `remoteEnv` (with `${localEnv|containerEnv|env:X[:default]}`, workspace variables and `null` to unset) reaches every child process through one environment overlay (terminals, run configurations, language servers, debuggers, build tools, git), and `postStartCommand` (string, array or parallel object) runs once per server start in the project root as a cancellable background task; a failure raises a notification with the exit code and the last output lines without blocking the project.
- Reload Environment (`remote.reloadEnvironment`, File menu and Find Action) re-resolves the login shell and `remoteEnv` without restarting the server, starting from the process's original environment so prepended PATH entries don't pile up; it lists the changed variables, notes that running processes keep their environment, and offers to restart language servers.
- The JSONC reader moves to `ide_core::jsonc` and is shared with ide-run.
Claude-Session: https://claude.ai/code/session_01Dq6jQQn8ZhRfkkyj3PRutA
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
An app started from Finder or the Dock took only PATH from the login shell, so
variables exported in rc files never reached agents, language servers, run
configurations or debug targets. Claude Code configured for Bedrock through
CLAUDE_CODE_USE_BEDROCK / AWS_REGION in ~/.zshrc fell back to the Anthropic API
and failed with 403.
The shell's environment is read once at startup (in the background when PATH
comes from the cache) and kept in memory only, since it may hold secrets. Spawns
add the variables this process lacks before their own.
- The IDE is a GUI-subsystem binary, so Windows allocated a fresh console
window for every console-subsystem child it started: one black window per
language server, per settings-driven restart, per debug adapter and per
toolchain probe, titled with the child's own path. Closing it killed the
child, which is how editing the language-server settings broke highlighting.
- Peer::spawn, the spawn point for every language server, wired stdio but never
passed CREATE_NO_WINDOW. The rustup-proxy probe, the DAP adapter, debugpy
probe, runInTerminal and cargo spawns, the SDK probes, the run-configuration
probes, the coverage exporter and tool diagnostics/downloads (curl, tar) had
the same gap, while git, cargo builds, gh, docker and run configurations
passed the flag inline — five copies of the magic constant, six subsystems
without it.
- Add ide_core::process::{CREATE_NO_WINDOW, hide_console_window} as the single
definition, route every spawn through it (tokio commands via as_std_mut()) and
fold the inline copies into it.
- Verified locally on Windows with a console-detached harness: a plain spawn
reports a visible console window (GetConsoleWindow + IsWindowVisible), the
patched Peer::spawn reports a console without a window. cargo check, cargo
clippy --all-targets and the affected test suites (249 tests) are green.
Co-authored-by: l0ng-ai <[email protected]>
Release builds use the GUI subsystem, so a console child spawned without
CREATE_NO_WINDOW gets its own console window. git, gh, docker, builds and
run configurations already set the flag; language servers, SDK and tool
probes, debug adapters, tool downloads, coverage export and perf did not.
Add ide_core::process::no_window and use it at every remaining spawn.
Fixes#16