Desktop/dock-launched clide inherits a sparse PATH (no ~/.local/bin, brew,
nvm, …), so pql/git/claude and PTY tools went missing. T-347 fixed only the
toolchain/pql path on Linux; env.dart's expander was still macOS-only and
claude/PTY/git used the raw PATH — the breakage recurred per spawn site
because there were three divergent expanders.
Consolidate into one resolver (lib/src/env/shell_env.dart):
- primeLoginShellPath(): probe the user's real login shell once at startup
(`$SHELL -l -c`, sentinel-framed, bounded timeout, graceful fallback to the
process PATH). Captures the user's actual PATH, not a hardcoded guess.
- expandToolPath(): the canonical merge (moved from toolchain_paths, which
re-exports it for its tests) — unions the well-known user/local bin dirs.
- resolvedToolPath(): currentSearchPath() + expandToolPath, the single call
every spawn site uses.
Routed through it: PTY children (registry.dart now overrides PATH), git
(env.dart → operations.dart), the toolchain probe (toolchain_paths), and
hosted claude (agent_bootstrap). Primed in main.dart's !kIsWeb boot. Deleted
the macOS-only env.dart copy and the cli_install copy.
Tests: new shell_env_test (probe + every fallback + merge); env_test and
cli_install_test updated to the consolidated surface. analyze clean, web wasm
build still green, make test green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Raise the declared minimums in pubspec.yaml to what our deps already
require: Flutter >=3.35.0 / Dart >=3.9.0 (was 3.19.0 / 3.5.0). alchemist
0.12 needs Flutter 3.32; Dart 3.9 first ships in Flutter 3.35, so 3.35 is
the binding floor. Pin the exact build toolchain in .fvmrc (Flutter
3.44.1).
Moving to the Dart 3.9 language level switches `dart format` to the new
"tall" style and enables two new lints. This commit is the resulting
mechanical churn, isolated from any behaviour change:
- whole-tree `dart format` reformat (tall style)
- `dart fix` for unnecessary_underscores + use_null_aware_elements
No runtime behaviour change; `make test` green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CliInstaller.inspect() gains a devTree state: when `clide` on PATH resolves
to a dev-tree build artifact (native/<plat>/clide, the Makefile's
CLIDE_CLI_BIN output) it's classified separately from a packaged install
rather than silently treated as "installed". needsInstall stays false for a
dev build (it's intentional on a checkout, not a reinstall prompt), and the
launch-time check surfaces it as an info note. install() flags fromDevTree +
notes it in the result message when the copied source is a dev build.
Closes the last open child of the T-208 "give Claude hands" initiative.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds the two missing cases that left lib/kernel/src/cli_install.dart:74
(default-environment constructor branch) and the builtin extension's
stale-GUI activation warning uncovered.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A command-palette / `clide` CLI verb (`clide.installCli`) copies the
bundled C client into ~/.local/bin, VS Code "Install code command" style,
so a user who runs the app without `make install` can still reach the CLI
from a shell. On launch the app detects when `clide` is missing from PATH
or resolves to a stale symlink into the Flutter GUI bundle (the dogfood
footgun: a bare `clide` launched a second app instead of querying the
socket) and notifies with a pointer to the command. `make build` now ships
the C client inside the app bundle so the affordance can self-install from
it; `make run` points it at the dev-tree client via CLIDE_CLI_BIN.
Detection and the copy live in the Flutter-free CliInstaller
(kernel/src/cli_install.dart) so they run under unit tests without a real
install.
Closes epic T-209 (ship the clide CLI on PATH).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>