Conversation
Move every remaining process caller in apps/cli/src onto apps/cli/src/platform/process, so the CLI has a single process implementation: git and gh invocations, daemon/worker/MCP-host children, cloudflared tunnels, worktree setup scripts, memory probes, the upgrade installer, the pid liveness probe, and PTY termination. Add runCommand/runCommandOk (bounded output, tree ended only when the caller abandons the command), runCommandSync for synchronous-by-contract callers (timeout required), isPidAlive, ManagedProcess.closed, SpawnSpec.windowsDetached, and their Promise facades. Enforce the boundary with scripts/check-cli-process-boundary.mjs, wired into pnpm check and check:quick, and point new code at the layer from apps/cli/AGENTS.md (replacing a stale, duplicated pr-poller paragraph to stay under the size gate). Record the decisions in the process tree layer note. Model: claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Sep 27, 2026
Model: claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Model: claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Resolve the Codex profile login spawn onto startProcess, and move main's new direct OS calls onto the process layer: the Codex profile pid probe uses isPidAliveSync and the profile logout uses runCommandText, recording its pid through a new CommandSpec.onSpawned hook. Model: claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…allers # Conflicts: # apps/cli/AGENTS.md
This branch has not been deployed
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.
Related issue
Refs #429
Stack
mainMerge in order; after each merge retarget the next PR to
main.Problem / pressure
#1065 moved only the ACP-related processes onto the Effect process layer. About 30 other files in
apps/cli/srcstill calledchild_process,cross-spawnorprocess.killdirectly, each with its own timeout and kill handling. With two implementations side by side, new code would keep copying the old one.Summary
apps/cli/src/platform/process/command.tsand others):runCommand/runCommandOkcollect output with a per-stream ceiling. The whole process tree is ended only when the caller stops waiting: timeout, interruption, or oversized output.runCommandSyncis for callers that must stay synchronous; it requires a timeout.isPidAlive.ManagedProcess.closed: exit plus drained stdio.SpawnSpec.windowsDetached.runCommandText,runCommandTextSync,startProcess,isPidAliveSync.open-browser, which now usesrundll32on Windows so URLs skip cmd parsing;lodysubcommand children;scripts/check-cli-process-boundary.mjsruns inpnpm checkandcheck:quick.platform/process/node-process.tsimportschild_process/cross-spawn, referencesnode-pty, or callsprocess.kill.apps/cli/AGENTS.mdpoints new code at the layer. A stale, duplicated pr-poller paragraph was replaced with a link to its scoped AGENTS.md to stay under the 8 KiB gate.lodysubcommand stays in the agent's process group;Visual explanation
flowchart TD subgraph Promise callers G["git / gh / probes"] --> RT["runCommandText(Sync)"] L["daemon, worker, MCP, cloudflared, installer, setup"] --> SP["startProcess"] I["IPC lock"] --> PA["isPidAliveSync"] P["PTY"] --> TP["terminatePtyProcessGroup"] end RT --> RC["runCommand / runCommandSync"] SP --> MP["spawnProcess + terminateTree"] PA --> AL["isPidAlive"] TP --> MP RC --> MP MP --> NP["NodeProcess (only OS access)"] AL --> NP Guard["check:cli-process-boundary"] -.forbids direct use.-> G & L & I & PBefore / after
pnpm checkon bypassesTerminationFailedsurfacedopen-browservia a cmd shell stringrundll32on WindowsTest plan
corepack pnpm checkpasses end-to-end: typecheck; lint with 0 errors; all package tests (CLI 3219 passed, 4 skipped); i18n; code-collab, platform, CLI process and public boundary guards.runCommandover real processes: output, stdin,CommandFailed, ENOENT.runCommandover the fake table: timeout ends the tree; a finished command keeps its daemon; oversized output fails at once and ends the tree.sleepis gone after a later step fails.open-browserargv per platform.git-identitytest, and a scattered-diffdiff-line-countstest.cross-spawnnow use thenodeProcessseam, so they no longer assert mock call counts.rundll32,windowsDetached);vite buildof the file-index and diff workers, which now pull in the facade (effect plus node builtins; no wasm or top-level await);lody-mcp-http-server.tsand thedaemon-runnerWorker spawn, which have typecheck coverage only.Context handoff
The Lody team asked that every dependent of the L0/L1 responsibilities move to the Effect implementation, so that no second implementation keeps pulling new code back, with AGENTS.md guidance and the PRs stacked. Electron main,
cli-supervisorandpackages/shared(13 files) run outside the CLI and are not covered here: that needs the layer moved into a shared package, which is a separate decision.🤖 Generated with Claude Code