Skip to content

refactor(cli): decompose runCli into explicit phase functions - #1373

Merged
thymikee merged 1 commit into
mainfrom
claude/runcli-phase-decomposition
Jul 23, 2026
Merged

refactor(cli): decompose runCli into explicit phase functions#1373
thymikee merged 1 commit into
mainfrom
claude/runcli-phase-decomposition

Conversation

@thymikee

Copy link
Copy Markdown
Member

What

Item 1 of the code-quality follow-ups: runCli() was one ~390-line function inlining every phase of a CLI invocation, sharing ~10 mutable let bindings by closure, with a catch block coupled to nearly all of them. It is now ~75 lines of orchestration over named phase functions, each with explicit inputs:

  • parseCliInputOrExit — parse + parse-error formatting, warnings, --version/help short-circuits, no-command usage exit
  • resolveRunContextOrExit — binding/platform defaulting, daemon paths, session, connection-defaults merge; produces the CliRunContext
  • runReactDevtoolsCli — the react-devtools special case (config + port-reverse callback)
  • resolveRemoteContext — batch-step parsing, remote-auth resolution, remote-connection materialization, the open-without-runtime-hints warning
  • buildClientConfig — the client config projection (was a closure)
  • maybeStartDaemonLogTail / createReplayReporterForTest — the two conditional setups
  • dispatchCliCommand — batch mapping + removed-runtime error + generic dispatch + unhandled-command throw
  • handleRunCliFailure + printDaemonLogTailOnError — the catch block, including the close-with-no-daemon success path

Behavior preservation

The one structural subtlety: the old catch block read effectiveFlags/resolvedRuntime mid-mutation through the closure — auth and materialization reassign them, and an error thrown between phases must be formatted with the partially-updated state. CliRunContext is therefore mutated in place by resolveRemoteContext (called out in the type's doc), so handleRunCliFailure sees exactly what the throwing phase saw. Exit codes, error formatting, phase order (warnings → version → help → binding → react-devtools/web → upgrade notifier → batch parse → auth → materialization → warning → cdp → log tail → dispatch), and the finally log-tail stop are unchanged; special-case bodies were moved verbatim.

Net +81 lines — this is a navigability refactor, not a deletion; the win is that each phase now has a name, an explicit signature, and a visible mutation contract.

Verification

typecheck · lint · check:fallow · format · full unit suite 487/487 (one earlier run hit the documented contention-timeout flake while three sibling worktrees ran concurrent suites; clean rerun on identical code).

runCli inlined parse/help short-circuits, binding resolution, remote
auth + materialization, four special-cased command kinds, dispatch, and
a catch block coupled to ~10 closure-mutated let bindings across ~390
lines. Each phase is now a named function over an explicit CliRunContext:
parseCliInputOrExit, resolveRunContextOrExit, runReactDevtoolsCli,
resolveRemoteContext, buildClientConfig, maybeStartDaemonLogTail,
createReplayReporterForTest, dispatchCliCommand, handleRunCliFailure.

The context is mutated in place by resolveRemoteContext so the failure
handler observes exactly the state the throwing phase saw — matching the
previous closure semantics, including the close-with-no-daemon success
path and daemon-log-tail-on-error. Behavior is unchanged; runCli itself
is now ~75 lines of orchestration.
@github-actions

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 1.8 MB 1.8 MB +1.7 kB
JS gzip 577.7 kB 578.0 kB +324 B
npm tarball 692.3 kB 692.6 kB +312 B
npm unpacked 2.4 MB 2.4 MB +1.7 kB

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 28.8 ms 28.8 ms +0.1 ms
CLI --help 58.7 ms 57.9 ms -0.8 ms

Top changed chunks:

Chunk Raw diff Gzip diff
dist/src/cli.js +1.7 kB +324 B

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Jul 23, 2026
@thymikee

thymikee commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

Reviewed exact head 885ae62e68ab08ddd182b233655c175df9ede8f6. The extracted CLI phases preserve the prior ordering and production route, including special exits, auth/materialization, batch parsing, CDP, log-tail setup, dispatch, diagnostics, and close-without-daemon handling. Partial remote context is retained for failure formatting, and the existing behavioral suites meaningfully cover the routed paths. All exact-head checks are green. No actionable findings; code review is ready for human review.

Residual risk: this broad refactor has no single dedicated phase-order/partial-mutation test, so future ordering changes still rely on distributed CLI coverage.

@thymikee
thymikee merged commit 9a61ac7 into main Jul 23, 2026
24 checks passed
@thymikee
thymikee deleted the claude/runcli-phase-decomposition branch July 23, 2026 07:57
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-07-23 07:57 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant