You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
rtk proxy streaming was fixed by the src/core/stream.rs work, but the fix is not global. Several filtered or nominally passthrough RTK command routes still do not emit stdout for long-running/watch/dev commands until the child exits, or until the parent is killed.
This is a different failure mode than the already-closed proxy-only issue: rtk proxy <cmd> streams, while rtk <recognized-filter-route> <watch/dev command> can still hang silently.
Verified behavior on current master
I tested current master (rtk 0.37.2 source tree) with fake long-running executables placed first in PATH. Each fake tool prints one line immediately and then sleeps forever. I measured whether RTK emitted the first stdout line within 2 seconds.
Streams correctly
STREAMS rtk proxy npm run dev
STREAMS rtk pnpm run dev
STREAMS rtk pnpm dev
STREAMS rtk docker logs -f web
STREAMS rtk docker compose logs -f web
STREAMS rtk kubectl logs -f web
Still broken before this fix
NO_STDOUT_WITHIN_2S rtk npm run dev
NO_STDOUT_WITHIN_2S rtk npm start
NO_STDOUT_WITHIN_2S rtk prettier --watch .
NO_STDOUT_WITHIN_2S rtk playwright codegen
NO_STDOUT_WITHIN_2S rtk gh pr checks 123 --watch
NO_STDOUT_WITHIN_2S rtk dotnet watch run
NO_STDOUT_WITHIN_2S rtk go run .
The user-visible effect is that an agent or human sees no progress and may kill/retry the command even though the child process is alive and already wrote output.
Minimal real-world repro
mkdir /tmp/rtk-stream-repro
cd /tmp/rtk-stream-repro
cat > package.json <<'JSON'{ "scripts": { "dev": "node -e \"console.log('dev-start'); setInterval(() => {}, 1000);\"" }}JSON
npm run dev # prints immediately
rtk proxy npm run dev # prints immediately
rtk npm run dev # no stdout before forced termination
Root cause
The merged streaming infrastructure is present, but not all command paths use it.
Important paths:
src/core/runner.rs: RunMode::Passthrough uses FilterMode::Passthrough, which inherits stdout/stderr and streams.
src/core/runner.rs: RunMode::Filtered calls stream::run_streaming(..., FilterMode::CaptureOnly), which captures stdout/stderr until EOF before applying a filter.
src/core/stream.rs: exec_capture() still uses cmd.output(), which waits for the child process to exit.
Some functions named run_passthrough were not actually streaming passthrough. For example, unsupported go and dotnet routes captured output and printed it only after completion.
So #222 was fixed for rtk proxy, but filtered routes and some passthrough-named routes remained EOF-buffered.
Summary
rtk proxystreaming was fixed by thesrc/core/stream.rswork, but the fix is not global. Several filtered or nominally passthrough RTK command routes still do not emit stdout for long-running/watch/dev commands until the child exits, or until the parent is killed.This is a different failure mode than the already-closed proxy-only issue:
rtk proxy <cmd>streams, whilertk <recognized-filter-route> <watch/dev command>can still hang silently.Verified behavior on current master
I tested current
master(rtk 0.37.2source tree) with fake long-running executables placed first inPATH. Each fake tool prints one line immediately and then sleeps forever. I measured whether RTK emitted the first stdout line within 2 seconds.Streams correctly
Still broken before this fix
The user-visible effect is that an agent or human sees no progress and may kill/retry the command even though the child process is alive and already wrote output.
Minimal real-world repro
Root cause
The merged streaming infrastructure is present, but not all command paths use it.
Important paths:
src/core/runner.rs:RunMode::PassthroughusesFilterMode::Passthrough, which inherits stdout/stderr and streams.src/core/runner.rs:RunMode::Filteredcallsstream::run_streaming(..., FilterMode::CaptureOnly), which captures stdout/stderr until EOF before applying a filter.src/core/stream.rs:exec_capture()still usescmd.output(), which waits for the child process to exit.run_passthroughwere not actually streaming passthrough. For example, unsupportedgoanddotnetroutes captured output and printed it only after completion.So
#222was fixed forrtk proxy, but filtered routes and some passthrough-named routes remained EOF-buffered.Related issues and PRs
rtk proxylong-running streaming bug. This issue is not the same becausertk proxy npm run devstreams whilertk npm run devdoes not..output()buffering, but the merged stream infrastructure did not eliminate all buffered filter paths.src/core/stream.rs,FilterMode, andrtk proxystreaming. This introduced the needed primitives, but many routes still useCaptureOnlyorexec_capture().rtk git pushcommand, it sometimes times out #963 and PR fix(git): stream push output to avoid spurious 30s timeout (#963) #1531:git pushtimeout has the same root cause pattern (Command::output()hiding progress/prompts), but PR fix(git): stream push output to avoid spurious 30s timeout (#963) #1531 only fixesgit push.--raw/--no-filteris related, but users should not need to know to opt out manually for commands that are inherently streaming.Suggested fix
RTK should detect inherently streaming invocations before choosing a buffered filtering path and run them with inherited stdout/stderr instead.
Practical detection heuristics:
--watch,--watchAll,-w--follow,-ffor log/follow tools such as Docker, kubectl, tail, journalctlwatch,dev,serve,startplaywright codegen,playwright show-report,go run,dotnet watchtail,nodemon,watchmanAlso, routes called
run_passthroughshould use actual passthrough execution (Stdio::inherit()/FilterMode::Passthrough), notCommand::output().Acceptance criteria
rtk npm run devemits output immediately and does not wait for EOF.rtk npm startemits output immediately and does not wait for EOF.rtk prettier --watch .emits output immediately.rtk playwright codegenemits output immediately.rtk gh pr checks <pr> --watchemits output immediately.rtk dotnet watch runemits output immediately.rtk go run .emits output immediately.rtk npm run buildandrtk gh pr checks <pr>remain filterable.