Skip to content

fix: show full binary path in user-facing command hints - #616

Closed
gaojunran wants to merge 5 commits into
jdx:mainfrom
gaojunran:fix/version-mismatch-binary-path
Closed

fix: show full binary path in user-facing command hints#616
gaojunran wants to merge 5 commits into
jdx:mainfrom
gaojunran:fix/version-mismatch-binary-path

Conversation

@gaojunran

@gaojunran gaojunran commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Problem

Several runtime messages tell the user to run pitchfork <cmd> ..., relying on whatever pitchfork resolves to on PATH. When the PATH binary differs from the one the user just invoked — e.g. a newer build in ~/.cargo/bin while PATH still points at an older /usr/bin/pitchfork, or under sudo (whose PATH differs) — following the hint runs the wrong binary and the problem persists.

Fix

Use the existing env::PITCHFORK_BIN (current_exe().canonicalize(), with a fallback) so hints name the exact binary:

Restart the supervisor with: /home/user/.cargo/bin/pitchfork supervisor start --force
Hint: ports below 1024 require elevated privileges. Try: sudo /home/user/.cargo/bin/pitchfork supervisor start

CLI-side hints (authoritative)

current_exe is the binary the user just ran — the right one to point at.

  • src/proxy/server.rssudo pitchfork supervisor start on low-port bind (the sudo case is especially important, since sudo's PATH differs).
  • src/ipc/client.rs — three ensure the supervisor is running with: pitchfork supervisor start connection-error helps; plus the original version-mismatch warning (Restart the supervisor with: <bin> supervisor start --force).
  • src/cli/proxy.rsPITCHFORK_PROXY_ENABLE=true pitchfork supervisor start.
  • src/proxy/trust.rspitchfork supervisor start in the missing-CA hint (install_cert is called from the CLI).
  • src/tui/ui.rsStart one with: pitchfork start <name>.

Other supervisor-side hints (operational, not version-sensitive)

current_exe is the running supervisor binary — a known-working binary. Fine for operational hints that aren't about upgrading.

  • src/proxy/server.rssudo <bin> supervisor start on low-port bind (elevation, not upgrade).
  • src/web/routes/api/proxies.rs — namespace registration hint.

Intentionally NOT converted

  • src/supervisor/ipc_handlers.rs — the version-mismatch restart hint is left as bare pitchfork supervisor start --force. This hint is version-sensitive (its whole purpose is to upgrade the supervisor), and the supervisor resolves PITCHFORK_BIN to its OWN (potentially old) binary. In the two-binaries case this PR handles (new CLI vs old supervisor), a full path there would point at the wrong (old) executable — reintroducing the problem on the other side. The supervisor can't know which CLI binary the user invoked (ConnectV2 only carries the version string), so the authoritative full-path hint is the CLI-side one in ipc/client.rs.

error.rs

The two IPC diagnostic helps (#[diagnostic(help("..."))]) are static attribute literals, so they can't interpolate a runtime path directly. Added a bin: String field to Timeout and ConnectionClosed and interpolate {bin} in the help text, populated from PITCHFORK_BIN at construction (CLI-side, authoritative).

Not changed

CLI help text / doc-comment examples (e.g. pitchfork start api, pitchfork logs ...) are intentionally left as pitchfork — that's documentation, not a runtime hint, and the program name should read as pitchfork.

CI flake mitigation

The Linux ci-bats job was flaking on ready output pattern matches and returns early because mise run test:bats runs bats --jobs 16 on a runner shared with the build/rust-tests/web-ui workflows, so the supervisor's tokio output processing can be starved for a few seconds. The < 3s early-return bound was too tight (one run detected ready at ~4s while the identical sibling "ready output regex" test passed the same run). Raised the bound to 8s (10s on Windows); the daemon's trailing sleep 10 still gives a deterministic ~11s regression baseline, so a regression that skips early return still fails the bound. The timer-based custom ready delay test is untouched (its ready_delay fires on a wall-clock timer, not stdout delivery).

Verification

  • cargo fmt --check
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo nextest run: 476 passed
  • mise run render: no doc diff (no CLI/schema change)

This PR description was generated by Claude Code.

The version-mismatch warning told users to restart the supervisor with
`pitchfork supervisor start --force`, relying on whatever `pitchfork`
resolves to on PATH. When the PATH binary differs from the one the user
just invoked, the hint restarts the wrong binary and the mismatch
persists.

Use the existing `env::PITCHFORK_BIN` (current_exe, canonicalized) so the
hint names the exact CLI binary the user invoked.
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

IPC connection diagnostics and supervisor guidance now use the configured CLI executable across connection, proxy, TUI, and API surfaces. IPC error variants carry the executable name, and ready-check tests allow additional CI scheduling and output-delivery latency.

Changes

Executable-aware IPC diagnostics

Layer / File(s) Summary
IPC diagnostics and connection guidance
src/ipc/client.rs, src/error.rs, src/supervisor/ipc_handlers.rs
IPC restart warnings, connection guidance, and rendered timeout/closed-connection help now use the resolved executable path; diagnostic payloads include the binary name.
Runtime guidance across CLI surfaces
src/cli/proxy.rs, src/proxy/*, src/tui/ui.rs, src/web/routes/api/proxies.rs
Proxy, certificate, privileged-port, daemon, and namespace instructions now render PITCHFORK_BIN instead of a hardcoded command.
Adjust ready-check timing tolerances
test/basic.bats
Raises early-return timing limits and platform-specific tolerances for ready-check tests, with comments explaining CI scheduling latency.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: jdx

Poem

A rabbit hopped along the CLI trail,
Making every command path prevail.
IPC warnings now point right,
While tests wait through CI night.
Hop, hop—guidance shines bright!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: user-facing command hints now show the full binary path instead of a hardcoded command.

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

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

@greptile-apps

greptile-apps Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces hardcoded pitchfork strings in all runtime user-facing hints with the actual binary path from env::PITCHFORK_BIN (current_exe().canonicalize() with a fallback), ensuring hints like "sudo … supervisor start" point to the exact binary the user invoked rather than whatever pitchfork resolves to on PATH. A secondary change relaxes bats CI timing bounds to reduce flakiness under parallel scheduling pressure.

  • src/error.rs: Timeout and ConnectionClosed grow a bin: String field so the miette help attribute literal can interpolate the binary path at construction time — the cleanest approach given that #[diagnostic(help(\"...\"))] is a static attribute.
  • All CLI-side and supervisor-side hint sites in proxy/server.rs, ipc/client.rs, cli/proxy.rs, proxy/trust.rs, tui/ui.rs, and web/routes/api/proxies.rs are updated consistently.
  • test/basic.bats: Early-return timing windows raised from 3 s → 8 s (10 s on Windows); the regression detection margin (daemon exits at ~11 s) is preserved.

Confidence Score: 5/5

Safe to merge — all changes are additive substitutions of a static string with a runtime-resolved path, with no logic changes and no broken pattern-match sites.

The change is mechanically straightforward: every hardcoded 'pitchfork' in user-facing hints is replaced with PITCHFORK_BIN.display(), which is already used widely across the codebase. The Timeout/ConnectionClosed enum changes add a struct field but no existing match sites were found. The bats timing relaxation is well-reasoned and preserves the regression detection margin. No logic paths were altered.

No files require special attention.

Important Files Changed

Filename Overview
src/error.rs Adds bin: String field to Timeout and ConnectionClosed variants to enable runtime path interpolation in diagnostic help text; no existing pattern-match sites in the codebase were broken.
src/ipc/client.rs All three ConnectionFailed help strings, both warn! version-mismatch messages, and the Timeout/ConnectionClosed constructors now embed the real binary path.
src/proxy/server.rs Low-port bind error now shows full binary path in the sudo hint; fix is correct and especially useful under sudo's sanitized PATH.
src/tui/ui.rs Both if/else branches now return String; Paragraph::new accepts String via Into<Text>, so no type error. Change is correct.
src/web/routes/api/proxies.rs Namespace registration error hint now includes the supervisor's binary path; supervisor-side as documented in the PR description.
test/basic.bats Early-return timing bounds relaxed from 3s to 8s (10s on Windows) to tolerate parallel-bats scheduling latency; regression path (~11s) still exceeds the bound.

Reviews (6): Last reviewed commit: "fix(supervisor): keep version-mismatch h..." | Re-trigger Greptile

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/ipc/client.rs`:
- Around line 34-37: Update the restart-hint construction around PITCHFORK_BIN
and the corresponding occurrences to shell-escape the executable path instead of
using raw Path::display() output. Use the project’s platform-appropriate quoting
mechanism, preserve the existing command structure, and add coverage for
executable paths containing spaces.
🪄 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: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: c8cd23e0-514f-40e4-9cb3-c7f160164d79

📥 Commits

Reviewing files that changed from the base of the PR and between 9062a6b and 3361f6c.

📒 Files selected for processing (1)
  • src/ipc/client.rs

Comment thread src/ipc/client.rs
Comment on lines +34 to +37
// Resolve the running CLI's binary path so the restart hint points at
// the exact binary the user invoked, not whatever `pitchfork` resolves
// to on PATH (which may be a different version).
let exe = env::PITCHFORK_BIN.display();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Shell-escape the executable path in restart hints.

Path::display() emits the raw path. If the binary is installed under a directory containing spaces or shell metacharacters, copying {exe} supervisor ... will fail or be interpreted incorrectly. Use platform-appropriate quoting/escaping and add coverage for paths containing spaces.

Also applies to: 54-54, 71-71

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/ipc/client.rs` around lines 34 - 37, Update the restart-hint construction
around PITCHFORK_BIN and the corresponding occurrences to shell-escape the
executable path instead of using raw Path::display() output. Use the project’s
platform-appropriate quoting mechanism, preserve the existing command structure,
and add coverage for executable paths containing spaces.

…rn tests

`pitchfork start` returns as soon as the ready_output pattern matches a
line on the daemon's stdout. Under CI, bats runs 16-way parallel
(`mise run test:bats` uses `bats --jobs 16`) on a runner shared with the
build, rust-tests, and web-ui workflows, so the supervisor's tokio
output processing can be starved for a few seconds. This made the tight
`[[ $elapsed -lt 3 ]]` bound flake: ci-bats(0) failed "ready output
pattern matches and returns early" with ready detected at ~4s while the
identical sibling "ready output regex" test passed the same run.

Raise the early-return bound to 8s (10s on Windows) for the two
ready_output tests. The daemon's trailing `sleep 10` still gives a
deterministic regression baseline (~11s on no-match daemon exit), so a
regression that skips early return still fails the bound.

The timer-based `custom ready delay` test is untouched; its ready_delay
fires on a wall-clock timer, not stdout delivery, so it is not subject
to this latency.

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/basic.bats`:
- Around line 330-334: Update the timing comment above max_elapsed in the
parallel-bats scheduling test to state that the expected regression path remains
approximately 11 seconds, preserving the test’s detection margin; leave the
8-second and Windows 10-second thresholds 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: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: b297e06a-8fbb-45ef-b45f-28bbffc54ea8

📥 Commits

Reviewing files that changed from the base of the PR and between 3361f6c and 777c1f4.

📒 Files selected for processing (1)
  • test/basic.bats

Comment thread test/basic.bats
@github-actions

Copy link
Copy Markdown
Contributor

This PR currently has failing checks. If this continues for 7 days, it will be closed automatically.

This is warning day 1 of 7.

Please update the PR when you have a chance. Feel free to reopen or create a new PR if it is closed and you'd like to continue working on it.

This comment was generated by an automated workflow.

@gaojunran gaojunran closed this Jul 18, 2026
@gaojunran gaojunran reopened this Jul 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This PR currently has failing checks. If this continues for 7 days, it will be closed automatically.

This is warning day 2 of 7.

Please update the PR when you have a chance. Feel free to reopen or create a new PR if it is closed and you'd like to continue working on it.

This comment was generated by an automated workflow.

The Windows threshold (10s) equals the daemon's trailing sleep, so the
prior "well under" wording was self-contradictory. Restate the detection
basis: the regression path (no early return → daemon exit ~11s) still
exceeds the 8s (10s on Windows) bound. Thresholds unchanged.
Several runtime messages told users to run `pitchfork <cmd> ...`, relying
on whatever `pitchfork` resolves to on PATH. When the PATH binary differs
from the one the user invoked (or under sudo, whose PATH differs), following
the hint runs the wrong binary. Use `crate::env::PITCHFORK_BIN`
(current_exe, canonicalized) so every hint names the exact binary.

CLI-side (current_exe = the binary the user just ran, authoritative):
- src/proxy/server.rs: "sudo pitchfork supervisor start" on low-port bind
- src/ipc/client.rs: three "ensure the supervisor is running with:
  pitchfork supervisor start" connection-error helps
- src/cli/proxy.rs: "PITCHFORK_PROXY_ENABLE=true pitchfork supervisor start"
- src/proxy/trust.rs: "pitchfork supervisor start" in the missing-CA hint
- src/tui/ui.rs: "Start one with: pitchfork start <name>"

Supervisor-side (current_exe = the running supervisor binary; correct in the
common single-binary / upgraded-in-place case):
- src/supervisor/ipc_handlers.rs: version-mismatch restart hint
- src/web/routes/api/proxies.rs: namespace registration hint

error.rs: the two IPC diagnostic helps (`#[diagnostic(help(...))]`) are
static attribute literals, so they can't interpolate a runtime path directly.
Add a `bin: String` field to `Timeout` and `ConnectionClosed` and
interpolate `{bin}` in the help text, populated from PITCHFORK_BIN at
construction.

CLI help-text / doc examples are intentionally left as `pitchfork` — that's
documentation, not a runtime hint.
@gaojunran gaojunran changed the title fix(ipc): show full binary path in version-mismatch warning fix: show full binary path in user-facing command hints Jul 19, 2026
Comment thread src/supervisor/ipc_handlers.rs

@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.

Caution

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

⚠️ Outside diff range comments (1)
src/ipc/client.rs (1)

54-54: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Shell-escape the executable path in command hints.

The binary path is inserted directly into the suggested commands without quotes. If PITCHFORK_BIN resolves to a path containing spaces, the suggested command will fail or be misinterpreted when a user copy-pastes it into their shell. Wrap the interpolated path in double quotes (\") at all sites.

  • src/ipc/client.rs#L54-L54: Add quotes around {exe}.
  • src/ipc/client.rs#L71-L71: Add quotes around {exe}.
  • src/ipc/client.rs#L142-L145: Format as with: \"{}\" supervisor start.
  • src/ipc/client.rs#L155-L158: Format as with: \"{}\" supervisor start.
  • src/ipc/client.rs#L168-L169: Format as with: \"{}\" supervisor start.
  • src/error.rs#L349-L362: Quote {bin} in both the Timeout and ConnectionClosed help strings.
  • src/supervisor/ipc_handlers.rs#L55-L56: Format as with: \"{}\" supervisor start.
  • src/cli/proxy.rs#L183-L186: Format as PITCHFORK_PROXY_ENABLE=true \"{}\" supervisor start.
  • src/proxy/server.rs#L1630-L1634: Format as Try: sudo \"{}\" supervisor start.
  • src/proxy/trust.rs#L140-L146: Format as \"{}\" supervisor start.
  • src/tui/ui.rs#L168-L173: Format as with: \"{}\" start <name>.
  • src/web/routes/api/proxies.rs#L89-L92: Replace the single quotes wrapping the entire command with double quotes specifically around the executable: Run: \"{}\" supervisor namespace add {} /path/to/dir.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/ipc/client.rs` at line 54, Shell-escape executable paths in every listed
command hint: update src/ipc/client.rs lines 54, 71, 142-145, 155-158, and
168-169; quote {exe} or format the executable as "{}" before supervisor start.
In src/error.rs lines 349-362, quote {bin} in both Timeout and ConnectionClosed
help strings. Apply the specified "{}" formatting in
src/supervisor/ipc_handlers.rs lines 55-56, src/cli/proxy.rs lines 183-186,
src/proxy/server.rs lines 1630-1634, src/proxy/trust.rs lines 140-146, and
src/tui/ui.rs lines 168-173. In src/web/routes/api/proxies.rs lines 89-92,
remove the command-wide single quotes and quote only the executable in the Run
hint.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/ipc/client.rs`:
- Line 54: Shell-escape executable paths in every listed command hint: update
src/ipc/client.rs lines 54, 71, 142-145, 155-158, and 168-169; quote {exe} or
format the executable as "{}" before supervisor start. In src/error.rs lines
349-362, quote {bin} in both Timeout and ConnectionClosed help strings. Apply
the specified "{}" formatting in src/supervisor/ipc_handlers.rs lines 55-56,
src/cli/proxy.rs lines 183-186, src/proxy/server.rs lines 1630-1634,
src/proxy/trust.rs lines 140-146, and src/tui/ui.rs lines 168-173. In
src/web/routes/api/proxies.rs lines 89-92, remove the command-wide single quotes
and quote only the executable in the Run hint.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 6151cd1e-941b-4d52-8bc8-ca03ee2892fd

📥 Commits

Reviewing files that changed from the base of the PR and between 52fde2d and 0930827.

📒 Files selected for processing (8)
  • src/cli/proxy.rs
  • src/error.rs
  • src/ipc/client.rs
  • src/proxy/server.rs
  • src/proxy/trust.rs
  • src/supervisor/ipc_handlers.rs
  • src/tui/ui.rs
  • src/web/routes/api/proxies.rs

Reverts the supervisor-side version-mismatch hint to bare `pitchfork`.
The supervisor resolves env::PITCHFORK_BIN via current_exe(), which is the
RUNNING supervisor's binary. In the two-binaries case this PR exists to
handle (new CLI vs old supervisor), that path points at the old binary, so
"Restart with: <path> supervisor start --force" restarts the wrong (old)
executable and the mismatch persists — the very problem this PR fixes, now
on the other side.

The supervisor cannot know which CLI binary the user invoked (ConnectV2 only
carries the version), so leave its hint as bare `pitchfork` (PATH-resolved).
The authoritative full-path hint is the CLI-side one in ipc/client.rs, where
current_exe is the binary the user just ran.

Other supervisor-side hints (proxy/server.rs port-elevation, web/proxies.rs
namespace add) are operational, not version-sensitive, so pointing at the
supervisor's own known-working binary is correct there.

jdx commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Thanks for the work here, but I don't think this change is worth it. Expanding these hints to the full current_exe().canonicalize() path helps a narrow edge case (mismatched PATH / sudo) at the cost of making every routine hint noisier for the common case. It's especially bad for mise users: the resolved path points into a version-pinned install dir (e.g. ~/.local/share/mise/installs/pitchfork/<version>/bin/pitchfork), which defeats mise's dynamic per-directory resolution and can point at a pruned binary after an upgrade — reintroducing the same staleness this set out to fix. The bare pitchfork hints read as documentation and resolve correctly under mise/PATH, so I'd rather keep them as-is.

This comment was generated by Claude Code.

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.

2 participants