Skip to content

Support terminal UI profiling - #6

Merged
kingwill101 merged 3 commits into
mainfrom
fix/tui-terminal-interrupts
May 1, 2026
Merged

kingwill101 merged 3 commits into
mainfrom
fix/tui-terminal-interrupts

Conversation

@kingwill101

@kingwill101 kingwill101 commented May 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add run --terminal and inherited-stdio launch mode for TUI and alternate-screen Dart/Flutter targets.
  • Add deterministic VM-service discovery for terminal-mode launches plus interrupt handling that finalizes available diagnostics on Ctrl+C/SIGTERM.
  • Add an artisanal widget TUI fixture, interrupt fixtures, docs/skill updates, and 0.3.0-wip changelog/version entries for the changed packages.

Tests

  • dart analyze packages/devtools_profiler_protocol packages/devtools_region_profiler packages/devtools_profiler_core packages/devtools_profiler_cli
  • dart test packages/devtools_profiler_protocol
  • dart test packages/devtools_region_profiler
  • dart test packages/devtools_profiler_cli
  • dart test packages/devtools_profiler_core
  • git diff --check
  • Manual PTY smoke: dart run packages/devtools_profiler_cli/bin/devtools_profiler.dart run --terminal --cwd packages/devtools_profiler_core/test/fixtures/profiled_app -- dart run bin/artisanal_widget_app.dart

Summary by CodeRabbit

  • New Features

    • Added --terminal flag to profile terminal UI (TUI) applications with direct stdin/stdout/stderr access
    • Added interrupt signal handling (Ctrl+C/SIGTERM) to finalize diagnostics before stopping profiling
  • Documentation

    • Updated README with examples and usage guidance for profiling TUI applications
    • Clarified --terminal constraints and incompatibility with --json output

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@kingwill101 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 55 minutes and 1 second before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5be62e62-2343-43e6-892b-7fea4f074d4e

📥 Commits

Reviewing files that changed from the base of the PR and between 13b676f and f5dc5a5.

📒 Files selected for processing (8)
  • README.md
  • packages/devtools_profiler_cli/README.md
  • packages/devtools_profiler_core/lib/src/capture/profile_runner.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_snapshot_capture.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_vm_hookup.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupt_parent.dart
  • packages/devtools_profiler_core/test/profile_runner_test.dart
📝 Walkthrough

Walkthrough

Introduces terminal UI profiling support via a --terminal flag enabling direct stdio access, interrupt signal handling for graceful diagnostics finalization, deterministic VM-service discovery for inherited-stdio Dart and Flutter launches, and timeout-bounded VM service operations. Adds test fixtures and comprehensive documentation.

Changes

Cohort / File(s) Summary
Documentation & Version Updates
README.md, CHANGELOG.md (both root and core), pubspec.yaml (both CLI and core)
Version bumps to 0.3.0-wip across CLI and core packages; extends READMEs with terminal-mode usage examples, constraints, and signal-handling behavior; adds changelog entries documenting new capabilities.
CLI Command Implementation
packages/devtools_profiler_cli/lib/src/cli/commands/capture_commands.dart, packages/devtools_profiler_cli/lib/src/presentation/cli_command.dart, packages/devtools_profiler_cli/lib/src/presentation/preparation.dart
Adds --terminal flag to run command with validation against --json incompatibility; wires processIoMode and handleInterruptSignals into profiler backend requests; augments reproduction command generation to preserve terminal mode; preserves terminatedByProfiler and processIoMode metadata in session results.
Core Profiling Request/Result Types
packages/devtools_profiler_core/lib/src/capture/profile_run_request.dart, packages/devtools_profiler_core/lib/src/capture/profile_run_result.dart
Introduces ProfileProcessIoMode enum (pipe, inheritStdio), handleInterruptSignals boolean flag in ProfileRunRequest, and corresponding processIoMode field in ProfileRunResult with JSON serialization/deserialization support.
Process Launch & Deterministic VM Service
packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart, packages/devtools_profiler_core/lib/src/capture/runner/profile_session_controller.dart
Implements deterministic VM-service attachment by pre-reserving ports and embedding expectedVmServiceUri in launch plans; conditionally selects inheritStdio vs. normal process start mode; avoids stdout/stderr scraping when expected URI is known; adjusts Dart/Flutter launch flags for inherited-stdio mode; makes stdout/stderr subscriptions optional.
Interrupt & Lifecycle Management
packages/devtools_profiler_core/lib/src/capture/profile_runner.dart
Adds process-level interrupt signal watching that races VM-service startup and process completion; marks sessions as terminatedByProfiler on interrupt; implements staged process termination and graceful finalization; updates result building to include processIoMode; refactors completion handling with interrupt-aware helpers.
VM Service Timeout Optimization
packages/devtools_profiler_core/lib/src/capture/runner/profile_session_snapshot_capture.dart, packages/devtools_profiler_core/lib/src/capture/runner/profile_session_vm_hookup.dart
Applies 2-second timeouts to VM-service RPC calls (getVM, getAllocationProfile, clearCpuSamples, getCpuSamples, getIsolate) to reduce shutdown polling overhead and bound exit-pause monitoring operations.
CLI & MCP Tests
packages/devtools_profiler_cli/test/cli_test.dart, packages/devtools_profiler_cli/test/mcp_server_test.dart
Validates --terminal flag parsing, --terminal/--json conflict detection, processIoMode propagation through profiler backend, and interrupt handling in session results; updates fake test runners to propagate processIoMode.
Core Integration Tests
packages/devtools_profiler_core/test/profile_runner_test.dart
Adds deterministic VM-service URI planning tests for Dart and Flutter under inheritStdio; includes end-to-end inherited-stdio profiling run for TUI fixture app and interrupt/diagnostics validation test verifying profiler-terminated sessions and artifact generation.
Test Fixtures & Apps
packages/devtools_profiler_core/test/fixtures/profiled_app/bin/artisanal_widget_app.dart, packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupt_parent.dart, packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupting_profiler.dart, packages/devtools_profiler_core/test/fixtures/profiled_app/pubspec.yaml
Creates TUI fixture app with alt-screen rendering and periodic CPU-burning updates; adds interrupt-parent script that signals on timing; introduces interrupting-profiler script demonstrating programmatic terminal-mode profiling with interrupt handling; updates fixture manifest with artisanal/artisanal_widgets dependencies and local devtools_profiler_core reference.
Skill Documentation
skills/devtools-profiler-local/SKILL.md
Documents --terminal usage for TUI applications, clarifies incompatibility with --json, describes interrupt behavior, and adds troubleshooting guidance to use --terminal for TUI rendering issues.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • Improve profiler artifact diagnostics #2: Modifies presentation/cli_command.dart for session CLI command generation; this PR augments the same code to include --terminal flag wiring based on processIoMode.

Poem

🐰 A terminal now runs free and whole,
With stdio flowing—raw and full control,
Signals caught mid-race, diagnostics saved with care,
VM services found, deterministically fair,
The profiler hops through TUIs with glee! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding support for profiling terminal UI applications, which is the core objective of this PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/tui-terminal-interrupts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 55 minutes and 1 second.

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/devtools_profiler_core/lib/src/capture/runner/profile_session_vm_hookup.dart (1)

121-130: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't treat timed-out getIsolate lookups as vanished isolates.

With the new timeout on Lines 122-124, this catch now also swallows TimeoutException. Removing that isolate from liveAppIsolateIds lets the later length check report allPaused: true even though the isolate may still be alive and merely slow to answer.

Suggested fix
               try {
                 final isolate = await vmService
                     .getIsolate(isolateRef.id!)
                     .timeout(_vmServiceExitPauseRequestTimeout);
                 if (isolate.pauseEvent?.kind == EventKind.kPauseExit) {
                   pausedExitIsolateIds.add(isolateRef.id!);
                 }
+              } on TimeoutException {
+                completeExitPauseSignal(allPaused: false);
+                return;
               } catch (_) {
                 // The isolate can disappear while the VM is shutting down.
                 liveAppIsolateIds.remove(isolateRef.id!);
               }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/devtools_profiler_core/lib/src/capture/runner/profile_session_vm_hookup.dart`
around lines 121 - 130, The catch currently treats any error (including
TimeoutException from vmService.getIsolate().timeout) as the isolate having
vanished and removes isolateRef.id from liveAppIsolateIds; change the error
handling in the block around
vmService.getIsolate/isolateRef/id/_vmServiceExitPauseRequestTimeout so that
TimeoutException is handled separately (do not remove the id and simply
skip/continue or log a timeout) while only non-timeout failures (e.g., RPC
errors or not-found) remove the id; update the catch to distinguish
TimeoutException (or TimeoutException type from dart:async) from other
exceptions and preserve the existing removal behavior only for the latter,
leaving pausedExitIsolateIds logic unchanged.
packages/devtools_profiler_core/lib/src/capture/profile_runner.dart (1)

74-85: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Start the interrupt watcher before any awaited startup work.

handleInterruptSignals is only enabled after launchProfiledProcess() returns. If the user hits Ctrl+C/SIGTERM during process launch, port reservation, or any other awaited startup step before Line 83, the profiler misses the signal and falls back to abrupt termination instead of returning partial diagnostics.

🔧 Suggested fix
-      launchedProcess = await launchProfiledProcess(
+      interruptWatcher = request.handleInterruptSignals
+          ? _ProfileRunSignalWatcher.start()
+          : null;
+
+      launchedProcess = await launchProfiledProcess(
         request: request,
         command: command,
         sessionId: sessionId,
         dtdUri: dtdSession.info.localUri.toString(),
         workingDirectory: workingDirectory,
       );
       process = launchedProcess.process;
       sessionController.childProcessId = process.pid;
-      interruptWatcher = request.handleInterruptSignals
-          ? _ProfileRunSignalWatcher.start()
-          : null;

If you want full coverage, move it even earlier so Ctrl+C also works during service registration.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools_profiler_core/lib/src/capture/profile_runner.dart` around
lines 74 - 85, Move starting of the interrupt watcher so it runs before any
awaited startup work: check request.handleInterruptSignals and call
_ProfileRunSignalWatcher.start() and assign to interruptWatcher before calling
await launchProfiledProcess(...); then call launchedProcess = await
launchProfiledProcess(...) and only after it returns set process =
launchedProcess.process and sessionController.childProcessId = process.pid as
before. Ensure the watcher variable is nullable/cleared as currently implemented
and that starting it early does not depend on the launched process being
available.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/devtools_profiler_cli/README.md`:
- Around line 69-82: Replace the placeholder example command in the README's
"Profile a terminal UI app" section with an executable, copy-pasteable fixture
command: update the --cwd value and the dart entrypoint so the sample uses the
repo's runnable TUI fixture (use
packages/devtools_profiler_core/test/fixtures/profiled_app as the --cwd and dart
run bin/artisanal_widget_app.dart as the command to run) while keeping the
--terminal flag and surrounding explanation intact.

In `@packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart`:
- Around line 517-548: The probing loop in _completeKnownVmServiceUri can hang
indefinitely if the target neither exposes the VM service nor exits; add an
overall timeout parameter (e.g., Duration vmServiceTimeout, defaulting to a
sensible value or passed from the request) and enforce it by computing a
deadline before the loop and checking elapsed time each iteration (alongside the
existing processExited check and _canConnectToVmService call); if the deadline
is exceeded and serviceUri is not completed, complete it with a
TimeoutException/StateError describing the timeout so callers can handle the
failure. Ensure the new timeout is threaded from the caller into
_completeKnownVmServiceUri and update any callers to pass vmServiceTimeout, and
keep existing behavior of completing with expectedVmServiceUri when
_canConnectToVmService succeeds and still honoring exitCodeFuture.
- Around line 499-505: Add a comment to _reserveLoopbackPort explaining the
TOCTOU race: state that binding-then-closing a ServerSocket to get a free
loopback port introduces a small window between server.close() and the target
process binding where another process could take the port, that this is an
accepted tradeoff for this profiling tooling, and suggest alternatives (e.g.,
letting the target pick an ephemeral port or using OS-specific reservation APIs)
for callers that need stronger guarantees; place the note directly above the
Future<int> _reserveLoopbackPort() declaration so maintainers see the limitation
when inspecting that function.
- Around line 266-294: The private helper _dartLaunchPlan lacks documentation
explaining key profiler/VM-service assumptions; add a dartdoc comment above the
_dartLaunchPlan function that (1) describes why '--pause-isolates-on-exit=false'
is used when processIoMode == ProfileProcessIoMode.inheritStdio and why the flag
is set (implicit true) for pipe mode (explain impact on isolate lifecycle and VM
service connection), and (2) documents the conditional use of
Platform.resolvedExecutable vs command.first (i.e., only substitute when
normalizedExecutableName(command.first) == 'dart' and command.first == 'dart' to
ensure using the running SDK's dart binary). Also mention expectedVmServiceUri
behavior and the rationale for '--disable-service-auth-codes' when inheriting
stdio; reference the symbols _dartLaunchPlan, ProfileProcessIoMode,
normalizedExecutableName, and CommandLaunchPlan in the comment.

In
`@packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupt_parent.dart`:
- Around line 8-10: Replace the fixed Timer in interrupt_parent.dart with a
readiness handshake: remove the Timer(const Duration(milliseconds: 1200), ...)
usage and instead listen on stdin (or read a line) for a specific "READY" token,
then call Process.killPid(parentPid, ProcessSignal.sigint) when that token is
received; keep the parentPid symbol as the target PID and update the test
harness to emit the "READY" line from the profiler under test when it has
finished startup so the fixture reliably triggers the interrupt only after
readiness.

---

Outside diff comments:
In `@packages/devtools_profiler_core/lib/src/capture/profile_runner.dart`:
- Around line 74-85: Move starting of the interrupt watcher so it runs before
any awaited startup work: check request.handleInterruptSignals and call
_ProfileRunSignalWatcher.start() and assign to interruptWatcher before calling
await launchProfiledProcess(...); then call launchedProcess = await
launchProfiledProcess(...) and only after it returns set process =
launchedProcess.process and sessionController.childProcessId = process.pid as
before. Ensure the watcher variable is nullable/cleared as currently implemented
and that starting it early does not depend on the launched process being
available.

In
`@packages/devtools_profiler_core/lib/src/capture/runner/profile_session_vm_hookup.dart`:
- Around line 121-130: The catch currently treats any error (including
TimeoutException from vmService.getIsolate().timeout) as the isolate having
vanished and removes isolateRef.id from liveAppIsolateIds; change the error
handling in the block around
vmService.getIsolate/isolateRef/id/_vmServiceExitPauseRequestTimeout so that
TimeoutException is handled separately (do not remove the id and simply
skip/continue or log a timeout) while only non-timeout failures (e.g., RPC
errors or not-found) remove the id; update the catch to distinguish
TimeoutException (or TimeoutException type from dart:async) from other
exceptions and preserve the existing removal behavior only for the latter,
leaving pausedExitIsolateIds logic unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: cb8ebe5a-a108-4d68-82ff-2db13dc15f54

📥 Commits

Reviewing files that changed from the base of the PR and between 87ca7a0 and 13b676f.

⛔ Files ignored due to path filters (1)
  • packages/devtools_profiler_core/test/fixtures/profiled_app/pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (25)
  • README.md
  • packages/devtools_profiler_cli/CHANGELOG.md
  • packages/devtools_profiler_cli/README.md
  • packages/devtools_profiler_cli/lib/src/cli/commands/capture_commands.dart
  • packages/devtools_profiler_cli/lib/src/presentation/cli_command.dart
  • packages/devtools_profiler_cli/lib/src/presentation/preparation.dart
  • packages/devtools_profiler_cli/pubspec.yaml
  • packages/devtools_profiler_cli/test/cli_test.dart
  • packages/devtools_profiler_cli/test/mcp_server_test.dart
  • packages/devtools_profiler_core/CHANGELOG.md
  • packages/devtools_profiler_core/README.md
  • packages/devtools_profiler_core/lib/src/capture/profile_run_request.dart
  • packages/devtools_profiler_core/lib/src/capture/profile_run_result.dart
  • packages/devtools_profiler_core/lib/src/capture/profile_runner.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_controller.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_snapshot_capture.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_vm_hookup.dart
  • packages/devtools_profiler_core/pubspec.yaml
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/artisanal_widget_app.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupt_parent.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupting_profiler.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/pubspec.yaml
  • packages/devtools_profiler_core/test/profile_runner_test.dart
  • skills/devtools-profiler-local/SKILL.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (7)
**/*.dart

📄 CodeRabbit inference engine (AGENTS.md)

**/*.dart: Follow idiomatic Dart and keep code easy to scan in split-screen views
Prefer multi-line strings over string concatenation for large text blocks, command output fixtures, JSON examples, and terminal snapshots
Keep lines near 80 characters where practical. Long identifiers and URLs may exceed that when wrapping would make the code harder to read
Use records for short-lived grouped return values instead of introducing one-off classes
Use patterns, if-case, and switch expressions when they make parsing or dispatch logic clearer
Use class modifiers such as sealed, final, base, and interface when they describe the intended inheritance boundary
Use digit separators for large numeric literals, for example timeouts, sample counts, and byte sizes
Use wildcard variables for intentionally unused callback parameters
Use null-aware collection elements when conditionally including nullable values in list or map literals
Use dot shorthands only when the inferred type is obvious from context
Use /// documentation comments for public APIs
Start doc comments with a short, single-sentence summary
Put a blank line after the first sentence when adding more detail in doc comments
Avoid repeating information that is already obvious from the declaration in documentation comments
Start method comments with third-person verbs, such as 'Returns', 'Starts', or 'Captures'
Start non-boolean property comments with a noun phrase
Start boolean property comments with 'Whether'
Use square brackets for in-scope identifiers, such as [ProfileRunRequest], [Duration], and [StateError]
Explain parameters, return values, and exceptions in prose rather than using tag-style documentation
Prefer fenced Markdown code blocks for examples in documentation comments
Keep Markdown simple; avoid HTML in documentation comments

Files:

  • packages/devtools_profiler_cli/test/mcp_server_test.dart
  • packages/devtools_profiler_cli/lib/src/presentation/cli_command.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_controller.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_vm_hookup.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupting_profiler.dart
  • packages/devtools_profiler_cli/lib/src/cli/commands/capture_commands.dart
  • packages/devtools_profiler_core/lib/src/capture/profile_run_result.dart
  • packages/devtools_profiler_core/lib/src/capture/profile_run_request.dart
  • packages/devtools_profiler_cli/lib/src/presentation/preparation.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_snapshot_capture.dart
  • packages/devtools_profiler_core/test/profile_runner_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/artisanal_widget_app.dart
  • packages/devtools_profiler_cli/test/cli_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupt_parent.dart
  • packages/devtools_profiler_core/lib/src/capture/profile_runner.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart
packages/devtools_profiler_*/**/*.dart

📄 CodeRabbit inference engine (AGENTS.md)

Consider documenting private helpers when they encode profiler behavior, artifact contracts, protocol semantics, or VM-service assumptions

Files:

  • packages/devtools_profiler_cli/test/mcp_server_test.dart
  • packages/devtools_profiler_cli/lib/src/presentation/cli_command.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_controller.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_vm_hookup.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupting_profiler.dart
  • packages/devtools_profiler_cli/lib/src/cli/commands/capture_commands.dart
  • packages/devtools_profiler_core/lib/src/capture/profile_run_result.dart
  • packages/devtools_profiler_core/lib/src/capture/profile_run_request.dart
  • packages/devtools_profiler_cli/lib/src/presentation/preparation.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_snapshot_capture.dart
  • packages/devtools_profiler_core/test/profile_runner_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/artisanal_widget_app.dart
  • packages/devtools_profiler_cli/test/cli_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupt_parent.dart
  • packages/devtools_profiler_core/lib/src/capture/profile_runner.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart
packages/devtools_profiler_**/pubspec.yaml

📄 CodeRabbit inference engine (AGENTS.md)

packages/devtools_profiler_**/pubspec.yaml: Do not add Flutter UI, web UI, or browser-only runtime dependencies to the profiler packages
Use hosted devtools_shared for shared VM and memory models; do not vendor package trees into this workspace

Files:

  • packages/devtools_profiler_core/pubspec.yaml
  • packages/devtools_profiler_cli/pubspec.yaml
packages/devtools_profiler_core/pubspec.yaml

📄 CodeRabbit inference engine (AGENTS.md)

devtools_profiler_core may depend on vm_service, dtd, and devtools_shared

Files:

  • packages/devtools_profiler_core/pubspec.yaml
packages/*/README.md

📄 CodeRabbit inference engine (AGENTS.md)

Package READMEs should explain how that package is used and how it fits into the profiler system. Prefer examples that agents can execute directly from the CLI

Files:

  • packages/devtools_profiler_core/README.md
  • packages/devtools_profiler_cli/README.md
README.md

📄 CodeRabbit inference engine (AGENTS.md)

Keep the root README.md end-user focused

Files:

  • README.md
packages/devtools_profiler_cli/pubspec.yaml

📄 CodeRabbit inference engine (AGENTS.md)

packages/devtools_profiler_cli/pubspec.yaml: Keep dart_mcp on the supported ^0.5.0 line unless the user asks for an upgrade
devtools_profiler_cli may depend on terminal/MCP/presentation packages such as artisanal and dart_mcp

Files:

  • packages/devtools_profiler_cli/pubspec.yaml
🧠 Learnings (13)
📓 Common learnings
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: Applies to packages/devtools_profiler_cli/pubspec.yaml : `devtools_profiler_cli` may depend on terminal/MCP/presentation packages such as `artisanal` and `dart_mcp`
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: For Flutter targets, remember that release mode, AOT builds, and browser/web targets do not expose the Dart VM service needed by this profiler
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: Applies to packages/devtools_profiler_cli/lib/**/command*.dart : Split large CLI commands into focused files instead of growing a monolithic command file
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: Applies to packages/devtools_profiler_*/**/*.dart : Consider documenting private helpers when they encode profiler behavior, artifact contracts, protocol semantics, or VM-service assumptions
📚 Learning: 2026-04-26T17:03:32.425Z
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: Applies to packages/devtools_profiler_cli/pubspec.yaml : Keep `dart_mcp` on the supported `^0.5.0` line unless the user asks for an upgrade

Applied to files:

  • packages/devtools_profiler_cli/test/mcp_server_test.dart
  • packages/devtools_profiler_core/pubspec.yaml
  • packages/devtools_profiler_cli/CHANGELOG.md
  • packages/devtools_profiler_core/test/fixtures/profiled_app/pubspec.yaml
  • packages/devtools_profiler_cli/pubspec.yaml
  • packages/devtools_profiler_core/CHANGELOG.md
📚 Learning: 2026-04-26T17:03:32.425Z
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: Applies to packages/devtools_profiler_cli/pubspec.yaml : `devtools_profiler_cli` may depend on terminal/MCP/presentation packages such as `artisanal` and `dart_mcp`

Applied to files:

  • packages/devtools_profiler_cli/test/mcp_server_test.dart
  • packages/devtools_profiler_cli/lib/src/presentation/cli_command.dart
  • packages/devtools_profiler_core/pubspec.yaml
  • packages/devtools_profiler_cli/CHANGELOG.md
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupting_profiler.dart
  • README.md
  • packages/devtools_profiler_cli/lib/src/cli/commands/capture_commands.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/pubspec.yaml
  • packages/devtools_profiler_cli/pubspec.yaml
  • packages/devtools_profiler_cli/README.md
  • skills/devtools-profiler-local/SKILL.md
  • packages/devtools_profiler_cli/lib/src/presentation/preparation.dart
  • packages/devtools_profiler_core/CHANGELOG.md
  • packages/devtools_profiler_core/test/profile_runner_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/artisanal_widget_app.dart
  • packages/devtools_profiler_cli/test/cli_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupt_parent.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart
📚 Learning: 2026-04-26T17:03:32.425Z
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: Applies to packages/devtools_profiler_*/**/*.dart : Consider documenting private helpers when they encode profiler behavior, artifact contracts, protocol semantics, or VM-service assumptions

Applied to files:

  • packages/devtools_profiler_cli/test/mcp_server_test.dart
  • packages/devtools_profiler_core/pubspec.yaml
  • packages/devtools_profiler_core/README.md
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_vm_hookup.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupting_profiler.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/pubspec.yaml
  • packages/devtools_profiler_cli/pubspec.yaml
  • packages/devtools_profiler_cli/README.md
  • packages/devtools_profiler_core/lib/src/capture/profile_run_request.dart
  • packages/devtools_profiler_cli/lib/src/presentation/preparation.dart
  • packages/devtools_profiler_core/CHANGELOG.md
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_snapshot_capture.dart
  • packages/devtools_profiler_core/test/profile_runner_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/artisanal_widget_app.dart
  • packages/devtools_profiler_cli/test/cli_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupt_parent.dart
  • packages/devtools_profiler_core/lib/src/capture/profile_runner.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart
📚 Learning: 2026-04-26T17:03:32.425Z
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: Applies to packages/devtools_profiler_cli/lib/**/command*.dart : Split large CLI commands into focused files instead of growing a monolithic command file

Applied to files:

  • packages/devtools_profiler_cli/lib/src/presentation/cli_command.dart
  • packages/devtools_profiler_core/pubspec.yaml
  • packages/devtools_profiler_cli/CHANGELOG.md
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupting_profiler.dart
  • README.md
  • packages/devtools_profiler_cli/lib/src/cli/commands/capture_commands.dart
  • packages/devtools_profiler_cli/pubspec.yaml
  • packages/devtools_profiler_cli/README.md
  • skills/devtools-profiler-local/SKILL.md
  • packages/devtools_profiler_core/test/profile_runner_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/artisanal_widget_app.dart
  • packages/devtools_profiler_cli/test/cli_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupt_parent.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart
📚 Learning: 2026-04-26T17:03:32.425Z
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: Applies to packages/devtools_profiler_core/pubspec.yaml : `devtools_profiler_core` may depend on `vm_service`, `dtd`, and `devtools_shared`

Applied to files:

  • packages/devtools_profiler_core/pubspec.yaml
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_vm_hookup.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/pubspec.yaml
  • packages/devtools_profiler_cli/pubspec.yaml
  • packages/devtools_profiler_core/CHANGELOG.md
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_snapshot_capture.dart
  • packages/devtools_profiler_core/test/profile_runner_test.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart
📚 Learning: 2026-04-26T17:03:32.425Z
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: Applies to packages/devtools_profiler_**/pubspec.yaml : Use hosted `devtools_shared` for shared VM and memory models; do not vendor package trees into this workspace

Applied to files:

  • packages/devtools_profiler_core/pubspec.yaml
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_vm_hookup.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/pubspec.yaml
  • packages/devtools_profiler_cli/pubspec.yaml
  • packages/devtools_profiler_core/CHANGELOG.md
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_snapshot_capture.dart
  • packages/devtools_profiler_core/test/profile_runner_test.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart
📚 Learning: 2026-04-26T17:03:32.425Z
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: Applies to packages/devtools_profiler_**/pubspec.yaml : Do not add Flutter UI, web UI, or browser-only runtime dependencies to the profiler packages

Applied to files:

  • packages/devtools_profiler_core/pubspec.yaml
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupting_profiler.dart
  • README.md
  • packages/devtools_profiler_cli/lib/src/cli/commands/capture_commands.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/pubspec.yaml
  • packages/devtools_profiler_cli/pubspec.yaml
  • packages/devtools_profiler_cli/README.md
  • skills/devtools-profiler-local/SKILL.md
  • packages/devtools_profiler_core/CHANGELOG.md
  • packages/devtools_profiler_core/test/profile_runner_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/artisanal_widget_app.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart
📚 Learning: 2026-04-26T17:03:32.425Z
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: `devtools_region_profiler` should stay small and safe to add to Dart or Flutter applications being profiled

Applied to files:

  • packages/devtools_profiler_core/pubspec.yaml
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupting_profiler.dart
  • README.md
  • packages/devtools_profiler_cli/lib/src/cli/commands/capture_commands.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/pubspec.yaml
  • packages/devtools_profiler_cli/pubspec.yaml
  • packages/devtools_profiler_core/lib/src/capture/profile_run_result.dart
  • packages/devtools_profiler_cli/README.md
  • skills/devtools-profiler-local/SKILL.md
  • packages/devtools_profiler_cli/lib/src/presentation/preparation.dart
  • packages/devtools_profiler_core/CHANGELOG.md
  • packages/devtools_profiler_core/test/profile_runner_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/artisanal_widget_app.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupt_parent.dart
📚 Learning: 2026-04-26T17:03:32.425Z
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: For Flutter targets, remember that release mode, AOT builds, and browser/web targets do not expose the Dart VM service needed by this profiler

Applied to files:

  • packages/devtools_profiler_core/pubspec.yaml
  • packages/devtools_profiler_core/README.md
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupting_profiler.dart
  • README.md
  • packages/devtools_profiler_cli/lib/src/cli/commands/capture_commands.dart
  • packages/devtools_profiler_cli/pubspec.yaml
  • packages/devtools_profiler_cli/README.md
  • skills/devtools-profiler-local/SKILL.md
  • packages/devtools_profiler_core/CHANGELOG.md
  • packages/devtools_profiler_core/lib/src/capture/runner/profile_session_snapshot_capture.dart
  • packages/devtools_profiler_core/test/profile_runner_test.dart
  • packages/devtools_profiler_cli/test/cli_test.dart
  • packages/devtools_profiler_core/lib/src/capture/profile_runner.dart
  • packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart
📚 Learning: 2026-04-26T17:03:32.425Z
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: Run formatting, analysis, and tests before handing work back using: dart format ., dart analyze ., and dart test on all profiler packages

Applied to files:

  • packages/devtools_profiler_core/pubspec.yaml
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupting_profiler.dart
  • README.md
  • packages/devtools_profiler_cli/lib/src/cli/commands/capture_commands.dart
  • packages/devtools_profiler_cli/pubspec.yaml
  • packages/devtools_profiler_core/lib/src/capture/profile_run_result.dart
  • packages/devtools_profiler_cli/README.md
  • packages/devtools_profiler_core/test/profile_runner_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/artisanal_widget_app.dart
  • packages/devtools_profiler_cli/test/cli_test.dart
  • packages/devtools_profiler_core/test/fixtures/profiled_app/bin/interrupt_parent.dart
📚 Learning: 2026-04-26T17:03:32.425Z
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: Applies to packages/*/README.md : Package READMEs should explain how that package is used and how it fits into the profiler system. Prefer examples that agents can execute directly from the CLI

Applied to files:

  • packages/devtools_profiler_core/README.md
  • README.md
  • packages/devtools_profiler_cli/README.md
📚 Learning: 2026-04-26T17:03:32.425Z
Learnt from: CR
Repo: kingwill101/devtools-profiler PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-26T17:03:32.425Z
Learning: Applies to **/*.dart : Prefer multi-line strings over string concatenation for large text blocks, command output fixtures, JSON examples, and terminal snapshots

Applied to files:

  • packages/devtools_profiler_cli/lib/src/cli/commands/capture_commands.dart
  • skills/devtools-profiler-local/SKILL.md
  • packages/devtools_profiler_cli/test/cli_test.dart
🔇 Additional comments (18)
packages/devtools_profiler_cli/lib/src/presentation/cli_command.dart (1)

21-22: Correctly preserves terminal-mode replay behavior.

Adding --terminal only for inherited-stdio sessions keeps the generated
reproduction command faithful to the original run.

packages/devtools_profiler_cli/lib/src/presentation/preparation.dart (1)

63-64: Good metadata propagation in prepared session output.

Keeping terminatedByProfiler and processIoMode preserves session semantics
for downstream rendering and CLI command reconstruction.

packages/devtools_profiler_core/lib/src/capture/runner/profile_session_controller.dart (1)

139-175: Result builder update is correctly wired for process I/O mode.

Requiring processIoMode at build time and persisting it in the result makes
the capture contract explicit and avoids accidental defaulting.

README.md (2)

72-85: Terminal profiling guidance is clear and actionable.

The new example and constraints communicate the intended TUI workflow well.


618-620: CLI reference update is consistent with runtime behavior.

Documenting --terminal and its --json incompatibility aligns with command
validation and user expectations.

packages/devtools_profiler_cli/lib/src/cli/commands/capture_commands.dart (3)

44-49: --terminal flag exposure is well integrated.

Option registration and usage examples make the new launch mode discoverable.

Also applies to: 68-68


84-90: Good guardrail for incompatible output modes.

The explicit --terminal + --json rejection prevents ambiguous runtime
behavior.


97-100: Request wiring for terminal mode is correct.

Mapping terminalMode to ProfileProcessIoMode.inheritStdio (else pipe) keeps
launch semantics deterministic.

packages/devtools_profiler_core/README.md (1)

102-119: Core README addition cleanly explains host-level terminal usage.

The sample and surrounding notes accurately describe when to use inherited stdio
and interrupt handling.

packages/devtools_profiler_cli/CHANGELOG.md (1)

3-12: Changelog entry is aligned with the shipped CLI behavior.

The 0.3.0-wip notes accurately summarize the terminal-mode and interrupt-flow
changes.

packages/devtools_profiler_core/CHANGELOG.md (1)

3-13: Core changelog update is accurate and complete for this feature set.

The entry reflects the key runtime and lifecycle improvements introduced here.

packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart (7)

11-23: LGTM!

Making the stream subscriptions optional is the right approach for inherited-stdio mode where stdout/stderr aren't piped. The relevant code snippet from profile_runner.dart confirms callers already handle nullability with ?.cancel().


26-38: LGTM!

The expectedVmServiceUri field with its documentation cleanly captures the deterministic attachment concept.


48-125: LGTM!

The conditional logic cleanly separates the two VM-service discovery paths: deterministic port probing for inherited-stdio mode vs. stdout/stderr scraping for pipe mode. The process exit handlers correctly complete the completer with an error if the URI isn't discovered.


381-425: LGTM!

The Flutter terminal mode functions correctly restrict --terminal to flutter run only, with clear error messaging explaining why flutter test isn't supported (no predictable VM-service URI). The port validation logic properly handles both missing and invalid port values.


479-497: LGTM!

The helper correctly parses both --option value and --option=value forms. The - prefix check on line 486 technically excludes negative numbers, but this is acceptable since port numbers must be positive.


550-565: LGTM!

The connectivity check is clean with proper resource cleanup in the finally block. The 100ms timeout is reasonable for local loopback probing.


344-379: LGTM!

The profiler arguments correctly handle terminal mode by:

  • Using a fixed port for deterministic attachment
  • Disabling service auth codes (necessary since we can't scrape them from output in inherited-stdio mode)

The auth code disabling is appropriate for local profiling scenarios where the VM service binds to loopback.

Comment thread packages/devtools_profiler_cli/README.md Outdated
Comment thread packages/devtools_profiler_core/lib/src/capture/runner/process_launch.dart Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 13b676fbd1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@kingwill101
kingwill101 merged commit 46f3a6e into main May 1, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant