Skip to content

feature: Refactor setup-first installer flow - #933

Merged
ndizazzo merged 11 commits into
mainfrom
feature/revise-install-paths
Jul 10, 2026
Merged

feature: Refactor setup-first installer flow#933
ndizazzo merged 11 commits into
mainfrom
feature/revise-install-paths

Conversation

@ndizazzo

@ndizazzo ndizazzo commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR implements the setup-first installer flow from .omo/plans/mesh-setup-installer.md and promotes the behavior spec to docs/specs/mesh-setup-installer.md.

Key changes:

  • Adds mesh-llm setup as the owner of native-runtime install/prune, optional service setup, and optional GitHub starring.
  • Simplifies Unix and PowerShell installers so scripts only install the binary and hand off to mesh-llm setup.
  • Keeps legacy installer flags compatibility-oriented, with warnings for policy now owned by setup.
  • Adds setup tests for planning, orchestration, runtime/prune behavior, service generation, GitHub prompts, and non-interactive paths.
  • Fails service setup closed when systemd/launchd start/enable/bootstrap/kickstart commands fail after service setup was requested.
  • Adds MESH_LLM_INSTALL_URL_BASE for Unix installer branch/deployment tests, matching the existing PowerShell test override.
  • Updates README, CLI docs, usage docs, website install docs, and generated website docs.

Example

./install.sh
✓ Installed mesh-llm to /home/ndizazzo/.local/bin

? Install the background service? [Y/n] y
? Star Mesh-LLM/mesh-llm on GitHub? [Y/n] 

✓ Mesh setup complete
  Runtime  skipped (--skip-runtime)
  Service  running
  GitHub   starred

Screenshot

image

Review Findings Addressed

During review against the plan/spec I found and fixed:

  • Correctness: service setup failures were only warnings. When service setup was requested, failed systemd/launchd activation could leave users believing setup succeeded. Added failing tests first, then changed service setup to return errors for requested activation failures.
  • Documentation/spec drift: root mesh_setup_spec.md was stale and untracked. Replaced it with canonical docs/specs/mesh-setup-installer.md and linked it from the docs indexes.
  • Deployment-testability gap: Unix installer lacked an asset-base override. Added MESH_LLM_INSTALL_URL_BASE and Bash coverage so branch release assets can be tested without unpublished GitHub release artifacts.
  • Release-manifest guardrail: Added a regression test proving generated native-runtime release manifests are single valid JSON documents.

Local Validation

  • cargo fmt --all
  • cargo fmt --all --check
  • cargo test -p mesh-llm-cli --lib
  • cargo test -p mesh-llm-commands --lib
  • cargo test -p mesh-llm --lib
  • python3 -m unittest scripts.tests.test_install_sh
  • python3 -m unittest scripts.tests.test_install_ps1 (PowerShell tests skipped where pwsh is unavailable locally)
  • python3 -m unittest scripts.tests.test_generate_native_runtime_release_manifest
  • cargo check -p mesh-llm
  • cargo clippy -p mesh-llm --all-targets -- -D warnings
  • just website-build
  • just build
  • Local smoke: ./target/debug/mesh-llm setup --skip-runtime --no-service --no-interactive

Remote Deployment Validation

Validated on both mesh1.patio51.com and mesh2.patio51.com:

  • Pulled branch feature/revise-install-paths.
  • Stopped existing mesh processes and removed the old ~/.local/bin/mesh-llm install.
  • Ran just release-build successfully on each ARM host.
  • Packaged each host's release binary into a local mesh-llm-aarch64-unknown-linux-gnu.tar.gz test asset with SHA256 sidecar.
  • Ran branch installer with MESH_LLM_INSTALL_URL_BASE=file:///tmp/mesh-setup-install-test/assets.
  • Confirmed checksum verification and install to ~/.local/bin.
  • Confirmed installed binary reports mesh-llm 0.68.0.
  • Built CPU native-runtime packages on both hosts with scripts/package-native-runtime.sh --build --backend cpu --target aarch64-unknown-linux-gnu.
  • Generated local native-runtimes.json, served it over localhost HTTP, and ran:
    MESH_LLM_NATIVE_RUNTIME_MANIFEST_URL=http://127.0.0.1:8123/native-runtimes.json ~/.local/bin/mesh-llm setup --no-service --no-interactive
  • Confirmed setup installed meshllm-native-runtime-linux-aarch64-cpu, pruned/checked cache, and summarized cleanly.
  • Re-ran setup on both hosts to confirm idempotent already installed; cache already clean behavior.

Note: the default setup manifest URL for this unreleased branch points at GitHub release v0.68.0, which does not exist yet, so remote validation used the supported native-runtime manifest override with locally packaged branch runtimes.

Summary by CodeRabbit

  • New Features

    • Added a guided mesh-llm setup flow after installation, including optional background service setup and an optional GitHub star prompt.
    • Added mesh-llm uninstall with dry-run, confirmation, and retention options.
    • Updated install scripts to launch or print the setup command after installation.
  • Documentation

    • Revised quickstart, CLI, install, troubleshooting, and website pages to reflect the new setup/uninstall flow and updated commands.
  • Bug Fixes

    • Improved uninstall safety and service handling across supported platforms.
    • Cleaned up terminal output for process termination messages.

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces a new mesh-llm setup command that handles native runtime installation/pruning, background service setup (systemd/launchd), and an optional GitHub star prompt via gh, plus a mesh-llm uninstall command for platform-aware cleanup. Bootstrap installers (install.sh/install.ps1) are simplified to only download the executable and hand off to mesh-llm setup. Documentation and website content are updated accordingly.

Changes

mesh-llm setup and uninstall flow

Layer / File(s) Summary
Setup model and planner
crates/mesh-llm-commands/src/setup/{environment,prompt,plan,planner,actions,mod}.rs, crates/mesh-llm-cli/src/parser.rs, crates/mesh-llm-cli/src/parser/setup_tests.rs, crates/mesh-llm-commands/src/lib.rs, crates/mesh-llm-commands/src/setup/tests.rs, crates/mesh-llm/src/commands/runtime.rs
Adds Command::Setup CLI parsing, SetupOptions/SetupEnvironment/SetupPlatform, SetupPrompter/SetupConfirmPrompt, SetupPlan/SetupStep types, and plan_setup validation logic with tests; loosens visibility on native runtime selector helpers.
Native runtime setup helpers
crates/mesh-llm-commands/src/runtime_native/setup_helpers.rs, crates/mesh-llm-commands/src/runtime_native.rs, crates/mesh-llm-commands/src/setup/cli_actions_tests.rs
Adds install_and_prune_native_runtime_for_setup orchestrating install then prune with non-fatal prune warnings, and refactors run_native_runtime_install/run_native_runtime_prune to reuse shared selection/prune helpers.
Service installation pipeline
crates/mesh-llm-commands/src/setup/service*.rs
Adds ServiceInstallContext/ServicePaths, systemd/launchd unit/plist template rendering, service file/runner writers, install_service for Linux/macOS, and extensive service tests.
GitHub star flow
crates/mesh-llm-commands/src/setup/github*.rs
Adds GhCommand/GhCommandRunner process execution, execute_github_star_plan eligibility/prompt logic, github_summary formatting, and tests covering skip/eligibility/prompt outcomes.
Setup orchestration and CLI wiring
crates/mesh-llm-commands/src/setup/{command,summary,command_tests,orchestration_tests}.rs, crates/mesh-llm-commands/src/terminal.rs, crates/mesh-llm/src/commands/{mod,setup,discover}.rs
Adds run_setup/run_setup_command, CliSetupActions, setup summary printing, terminal confirm/styling helpers, and CLI dispatch wiring for Command::Setup.
Uninstall command
crates/mesh-llm-commands/src/uninstall.rs, crates/mesh-llm-cli/src/parser/uninstall_tests.rs
Adds UninstallOptions/UninstallPlan/UninstallOutcome, platform-aware plan construction and execution, JSON/human rendering, and tests.
Installer handoff changes
install.sh, install.ps1, scripts/tests/test_install_{sh,ps1}.py, scripts/tests/test_generate_native_runtime_release_manifest.py
Simplifies installers to download a single host executable and hand off to mesh-llm setup/mesh-llm.exe setup, reworks checksum/asset selection, and updates test suites.
Documentation and website updates
README.md, docs/*, website/src/**
Updates README, CLI/USAGE docs, adds the setup installer spec, revises install/quickstart/troubleshooting pages, and adds “Finish setup” UI blocks.

Estimated code review effort: 4 (Complex) | ~75 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant InstallScript as install.sh / install.ps1
  participant CLI as mesh-llm setup
  participant Runtime as Native runtime helpers
  participant Service as Service installer
  participant GitHub as gh CLI

  User->>InstallScript: run install command
  InstallScript->>InstallScript: download executable, update PATH
  InstallScript->>CLI: run or print "mesh-llm setup"
  CLI->>Runtime: install_and_prune_native_runtime_for_setup
  Runtime-->>CLI: SetupNativeRuntimeOutcome
  CLI->>Service: install_service (systemd/launchd)
  Service-->>CLI: ServiceInstallReport
  CLI->>GitHub: execute_github_star_plan
  GitHub-->>CLI: SetupGitHubOutcome
  CLI-->>User: print_setup_summary
Loading
sequenceDiagram
  participant User
  participant CLI as mesh-llm uninstall
  participant Env as detect_uninstall_environment
  participant Plan as plan_uninstall
  participant Exec as execute_uninstall_plan

  User->>CLI: mesh-llm uninstall [--dry-run|--yes]
  CLI->>Env: detect platform, paths, binary
  Env-->>CLI: UninstallEnvironment
  CLI->>Plan: build steps from options
  Plan-->>CLI: UninstallPlan
  alt dry-run
    CLI-->>User: render_plan
  else confirmed
    CLI->>Exec: run each UninstallStep
    Exec-->>CLI: UninstallOutcome
    CLI-->>User: render_outcome
  end
Loading

Possibly related PRs

  • Mesh-LLM/mesh-llm#806: The website/docs updates for the new "Finish setup" flow build directly on the meshllm.cloud website scaffolding introduced there.
  • Mesh-LLM/mesh-llm#873: Both PRs modify crates/mesh-llm-commands/src/runtime_native.rs's runtime selection resolution logic, which this PR's setup_helpers builds upon.

Suggested reviewers: michaelneale, i386

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.77% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: refactoring the installer into a setup-first flow.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/revise-install-paths

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (1)
crates/mesh-llm-cli/src/parser.rs (1)

1521-1567: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Move the new setup parsing tests out of parser.rs.

parser.rs is already past the 2,000-line limit, and adding more inline setup-specific tests keeps growing the largest CLI file instead of splitting by responsibility. Please peel these tests into a dedicated parser test module/file. As per coding guidelines, **/*.rs: "Do not add Rust source files over 2,000 lines. If a file is approaching that size, split it by responsibility into an owning module instead of adding more code to the oversized file."

🤖 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 `@crates/mesh-llm-cli/src/parser.rs` around lines 1521 - 1567, The new setup
parsing tests should be moved out of the oversized parser.rs test section into a
dedicated parser test module/file. Extract the
setup_command_parses_without_plugin_fallback,
setup_command_rejects_conflicting_service_flags, and
setup_command_rejects_skip_doctor_flag cases so parser.rs stops growing past the
file-size limit, and keep the assertions and Cli::parse_from /
Cli::try_parse_from coverage intact in the new test location.

Source: Coding guidelines

🤖 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 `@crates/mesh-llm-commands/src/setup/github.rs`:
- Around line 7-8: The GITHUB_STAR_PROMPT string in github.rs currently
hardcodes a yes/no suffix that duplicates what
dialoguer::Confirm::with_prompt(...).default(true) already adds. Update the
prompt constant used by the GitHub setup flow to remove the trailing [Y/n], or
change the Confirm configuration if custom suffix handling is required, so the
prompt does not render twice.

In `@crates/mesh-llm-commands/src/setup/prompt.rs`:
- Around line 35-46: The confirm flow in confirm_yes_no currently collapses both
Esc/cancel and dialoguer errors into None, which SetupPromptDefault::resolve
then treats as approval. Update confirm_yes_no so that an aborted or failed
Confirm::interact_opt() is preserved as a non-approval outcome (or explicitly
returned as cancel/skip), and adjust SetupPromptDefault::resolve to treat that
outcome as a отказ/skip instead of falling back to the default true behavior.

In `@crates/mesh-llm-commands/src/setup/service_templates.rs`:
- Around line 17-23: The Bash template in render_service_runner embeds
binary_path and env_file directly into quoted shell assignments, so paths
containing special characters can break the generated runner or alter runtime
values. Update the template generation to shell-escape both Path values before
inserting them into the BIN and ENV_FILE assignments, and keep the rest of the
script unchanged so launchd can safely start the service from any valid path.
- Around line 42-55: render_launchd_plist currently injects dynamic values
directly into the XML text nodes, which can break the plist when paths contain
XML-reserved characters. Update render_launchd_plist to XML-escape the values
for service_runner, home_dir, stdout_log, and stderr_log before formatting the
plist string, keeping SERVICE_LABEL unchanged if it is already safe. Use the
existing render_launchd_plist function and its local string interpolation points
to locate the fix.

In `@install.sh`:
- Around line 320-340: The libcudart version detection in detect_cuda_major() is
using an over-escaped regex that will miss real shared library names. Update
both grep patterns in the nvcc/libcudart fallback probes to match
libcudart.so.<version> correctly, so detect_cuda_major can extract the CUDA
major version from versioned libcudart libraries instead of returning empty and
falling back unnecessarily.

In `@website/src/docs/pages/CLI.md`:
- Around line 37-49: The CLI docs contain a duplicated “Finish a fresh install”
introduction in the section around the mesh-llm setup command. Update the
content in CLI.md by either removing the standalone introductory block before
the numbered list or changing the list structure so the first numbered item does
not repeat the same heading; use the duplicated “Finish a fresh install” text
and the mesh-llm setup example as the anchors when editing.

---

Nitpick comments:
In `@crates/mesh-llm-cli/src/parser.rs`:
- Around line 1521-1567: The new setup parsing tests should be moved out of the
oversized parser.rs test section into a dedicated parser test module/file.
Extract the setup_command_parses_without_plugin_fallback,
setup_command_rejects_conflicting_service_flags, and
setup_command_rejects_skip_doctor_flag cases so parser.rs stops growing past the
file-size limit, and keep the assertions and Cli::parse_from /
Cli::try_parse_from coverage intact in the new test location.
🪄 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: CHILL

Plan: Pro Plus

Run ID: 82660c3f-4d83-4194-8332-c6a2d874d9df

📥 Commits

Reviewing files that changed from the base of the PR and between 232c85a and afdbbe8.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (49)
  • README.md
  • crates/mesh-llm-cli/src/parser.rs
  • crates/mesh-llm-commands/Cargo.toml
  • crates/mesh-llm-commands/src/lib.rs
  • crates/mesh-llm-commands/src/runtime_native.rs
  • crates/mesh-llm-commands/src/runtime_native/setup_helpers.rs
  • crates/mesh-llm-commands/src/setup/actions.rs
  • crates/mesh-llm-commands/src/setup/cli_actions_tests.rs
  • crates/mesh-llm-commands/src/setup/command.rs
  • crates/mesh-llm-commands/src/setup/command_tests.rs
  • crates/mesh-llm-commands/src/setup/environment.rs
  • crates/mesh-llm-commands/src/setup/github.rs
  • crates/mesh-llm-commands/src/setup/github_runner.rs
  • crates/mesh-llm-commands/src/setup/github_tests.rs
  • crates/mesh-llm-commands/src/setup/mod.rs
  • crates/mesh-llm-commands/src/setup/orchestration_tests.rs
  • crates/mesh-llm-commands/src/setup/plan.rs
  • crates/mesh-llm-commands/src/setup/planner.rs
  • crates/mesh-llm-commands/src/setup/prompt.rs
  • crates/mesh-llm-commands/src/setup/service.rs
  • crates/mesh-llm-commands/src/setup/service_files.rs
  • crates/mesh-llm-commands/src/setup/service_paths.rs
  • crates/mesh-llm-commands/src/setup/service_runner.rs
  • crates/mesh-llm-commands/src/setup/service_templates.rs
  • crates/mesh-llm-commands/src/setup/service_tests.rs
  • crates/mesh-llm-commands/src/setup/summary.rs
  • crates/mesh-llm-commands/src/setup/test_support.rs
  • crates/mesh-llm-commands/src/setup/tests.rs
  • crates/mesh-llm/src/commands/mod.rs
  • crates/mesh-llm/src/commands/runtime.rs
  • crates/mesh-llm/src/commands/setup.rs
  • docs/CLI.md
  • docs/README.md
  • docs/USAGE.md
  • docs/specs/mesh-setup-installer.md
  • install.ps1
  • install.sh
  • scripts/tests/test_generate_native_runtime_release_manifest.py
  • scripts/tests/test_install_ps1.py
  • scripts/tests/test_install_sh.py
  • website/src/_includes/components/cta-terminal.njk
  • website/src/_includes/sections/hero.njk
  • website/src/docs/pages/CLI.md
  • website/src/docs/pages/installing-linux.md
  • website/src/docs/pages/installing-macos.md
  • website/src/docs/pages/installing-mesh.md
  • website/src/docs/pages/installing-windows.md
  • website/src/docs/pages/quickstart.md
  • website/src/docs/pages/troubleshooting.md

Comment thread crates/mesh-llm-commands/src/setup/github.rs Outdated
Comment thread crates/mesh-llm-commands/src/setup/prompt.rs Outdated
Comment thread crates/mesh-llm-commands/src/setup/service_templates.rs
Comment thread crates/mesh-llm-commands/src/setup/service_templates.rs
Comment thread install.sh
Comment thread website/src/docs/pages/CLI.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@crates/mesh-llm-commands/src/uninstall.rs`:
- Around line 293-295: The remove_binary helper is routing executable deletion
through remove_recursively, which can delete directories and still fails for
self-uninstall on Windows because the running exe is locked. Update
remove_binary to validate that the target is a file or symlink rather than a
directory, and use a Windows-specific deferred-delete path for
current_exe/self-removal instead of deleting in-process. Keep the fix centered
on remove_binary and the uninstall flow that determines the binary path.

In `@docs/specs/mesh-setup-installer.md`:
- Around line 148-149: Clarify the `--purge-config` and `--keep-config` behavior
in the installer spec so the conflict is explicit: state that the flags are
mutually exclusive or, if both are provided, that `--keep-config` takes
precedence as in the current `mesh-setup-installer` behavior. Update the option
descriptions in the spec around the supported flags to match this rule and
ensure the wording is unambiguous for future CLI parsing and implementations.
🪄 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: CHILL

Plan: Pro Plus

Run ID: 07e59e93-37e2-40b5-aae4-3f93bb7a12e1

📥 Commits

Reviewing files that changed from the base of the PR and between 013c26a and e36e144.

📒 Files selected for processing (14)
  • README.md
  • crates/mesh-llm-cli/src/parser.rs
  • crates/mesh-llm-cli/src/parser/uninstall_tests.rs
  • crates/mesh-llm-commands/src/lib.rs
  • crates/mesh-llm-commands/src/uninstall.rs
  • crates/mesh-llm/src/commands/mod.rs
  • docs/CLI.md
  • docs/specs/mesh-setup-installer.md
  • website/src/docs/pages/CLI.md
  • website/src/docs/pages/hardware-support.md
  • website/src/docs/pages/installing-linux.md
  • website/src/docs/pages/installing-macos.md
  • website/src/docs/pages/installing-mesh.md
  • website/src/docs/pages/installing-windows.md
✅ Files skipped from review due to trivial changes (9)
  • website/src/docs/pages/hardware-support.md
  • README.md
  • crates/mesh-llm-cli/src/parser/uninstall_tests.rs
  • website/src/docs/pages/installing-mesh.md
  • website/src/docs/pages/installing-windows.md
  • website/src/docs/pages/CLI.md
  • website/src/docs/pages/installing-linux.md
  • docs/CLI.md
  • website/src/docs/pages/installing-macos.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • crates/mesh-llm-commands/src/lib.rs
  • crates/mesh-llm/src/commands/mod.rs
  • crates/mesh-llm-cli/src/parser.rs

Comment thread crates/mesh-llm-commands/src/uninstall.rs
Comment thread docs/specs/mesh-setup-installer.md
@ndizazzo ndizazzo changed the title Add setup-first installer flow feature: Refactor setup-first installer flow Jun 30, 2026
@ndizazzo
ndizazzo force-pushed the feature/revise-install-paths branch 3 times, most recently from 48fb272 to 96d43cb Compare June 30, 2026 18:38
@ndizazzo
ndizazzo requested a review from i386 July 1, 2026 03:05
@ndizazzo ndizazzo linked an issue Jul 1, 2026 that may be closed by this pull request
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

This pull request has not been updated in at least 5 days. It will be closed after 7 days of inactivity to keep the active review queue current. Please update it within 2 days if the changes are still moving forward.

@github-actions github-actions Bot added the stale label Jul 7, 2026
@ndizazzo

ndizazzo commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator Author

@CodeRabbit full review

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

♻️ Duplicate comments (1)
crates/mesh-llm-commands/src/setup/service_templates.rs (1)

25-40: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

EnvironmentFile= path is not escaped for systemd specifiers.

render_systemd_unit escapes binary_path in the ExecStart= line via systemd_quote_token, but service_env_file is written raw via .display() into EnvironmentFile=-{service_env_file} (Line 37). Systemd specifier expansion (%h, %%, etc.) applies to EnvironmentFile= just as it does to ExecStart=; if service_env_file (derived from dirs::config_dir()/home dir) ever contains a literal %, the generated unit will misinterpret it. This is the same escaping-gap class already fixed for render_service_runner and render_launchd_plist in this file per prior review comments.

Proposed fix
     format!(
         "# mesh-llm serve (startup models come from {mesh_config_file})\n[Unit]\nDescription=Mesh LLM user service\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nEnvironmentFile=-{service_env_file}\n\n{exec_line}\nWorkingDirectory=%h\nRestart=on-failure\nRestartSec=5\n\n[Install]\nWantedBy=default.target\n",
         mesh_config_file = mesh_config_file.display(),
-        service_env_file = service_env_file.display(),
+        service_env_file = systemd_quote_token(&service_env_file.to_string_lossy()).trim_matches('"'),
         exec_line = exec_line,
     )

Alternatively, escape only the % character (systemd's specifier escape) since EnvironmentFile= doesn't require full shell quoting, just specifier-safety.

Please confirm systemd specifier expansion applies to EnvironmentFile= values (not just ExecStart=):

Does systemd expand % specifiers in EnvironmentFile= directive
🤖 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 `@crates/mesh-llm-commands/src/setup/service_templates.rs` around lines 25 -
40, The generated systemd unit in render_systemd_unit leaves service_env_file
unescaped in EnvironmentFile=, so systemd specifier expansion can misread
literals like %. Update render_systemd_unit to apply the same systemd-safe
escaping used elsewhere in this file (for example the escaping pattern already
used by render_service_runner/render_launchd_plist) before writing
EnvironmentFile=-{service_env_file}, while keeping ExecStart handling unchanged.
🧹 Nitpick comments (9)
crates/mesh-llm-commands/src/setup/service_files.rs (1)

8-22: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

TOCTOU on env file existence check.

ensure_service_env_file checks exists() then writes; a concurrent setup invocation could race between the check and the write. Low practical risk given setup is a manual interactive/one-shot command, but worth noting.

🤖 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 `@crates/mesh-llm-commands/src/setup/service_files.rs` around lines 8 - 22,
ensure_service_env_file has a TOCTOU race because it checks Path::exists()
before writing, so concurrent invocations can both pass the check and then
overwrite or race on the same env file. Update ensure_service_env_file to make
file creation atomic by using a create-if-missing approach or handling the
already-exists case at write time, while keeping the parent-directory setup and
render_service_env_file flow intact.
crates/mesh-llm-commands/src/setup/github_runner.rs (1)

113-138: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Minor race between timeout kill and process exit.

If child exits right as the timeout threshold is reached, child.kill() can fail (process already reaped), yielding a KillFailed error even though the command actually completed. Not critical, but consider a final try_wait() check inside the timeout branch before calling kill().

🤖 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 `@crates/mesh-llm-commands/src/setup/github_runner.rs` around lines 113 - 138,
The timeout handling in the GitHub runner loop can misclassify a process that
exits right as the deadline is hit. In the `run`/polling loop around
`child.try_wait()`, add a final `try_wait()` check inside the
`started_at.elapsed() >= self.timeout` branch before calling `child.kill()`, and
only kill if the child is still running; this should keep
`GhCommandError::TimedOut`, `KillFailed`, and the `GhCommandOutput` flow aligned
with the actual process state.
crates/mesh-llm-commands/src/setup/service_tests.rs (1)

66-73: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Missing test coverage for EnvironmentFile= escaping.

Given the escaping gap flagged in service_templates.rs (unescaped service_env_file in EnvironmentFile=), consider adding a test analogous to launchd_plist_escapes_xml_specials_in_paths / launchd_runner_escapes_shell_specials_in_paths that exercises a service_env_file path containing % to lock in correct systemd-specifier-safe behavior once fixed.

🤖 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 `@crates/mesh-llm-commands/src/setup/service_tests.rs` around lines 66 - 73,
Add coverage in service_tests around render_systemd_unit to exercise a
service_env_file path containing % so we lock in systemd-specifier-safe escaping
for EnvironmentFile=. Mirror the style of the existing launchd escape tests, but
target render_systemd_unit and verify the generated unit contains the properly
escaped EnvironmentFile value rather than the raw path.
crates/mesh-llm-commands/src/setup/command.rs (1)

54-54: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Verify line 54 is within rustfmt's width limit.

This line (with 4-space indent) appears to run past the typical 100-column rustfmt default. As per coding guidelines, Rust files touched by this change must be formatted before committing.

♻️ Suggested formatting
-    let mut actions = CliSetupActions::new(args.environment, args.configured, args.options.verbose);
+    let mut actions =
+        CliSetupActions::new(args.environment, args.configured, args.options.verbose);
🤖 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 `@crates/mesh-llm-commands/src/setup/command.rs` at line 54, The initialization
of CliSetupActions in command.rs appears to exceed rustfmt’s preferred width.
Reformat the statement in the setup command so it stays within the standard Rust
formatting limits, and then run rustfmt on the touched Rust code to ensure the
command module remains consistently formatted.

Source: Coding guidelines

crates/mesh-llm-commands/src/setup/summary.rs (2)

166-176: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Compact GitHub summary silently omits actionable states.

CliUnavailable and NotAuthenticated are dropped from the compact "GitHub" line (fall to _ => None), unlike service_brief, which always surfaces a status (even "not recorded"). Users who hit these states get no compact-mode signal that GitHub star setup didn't run, only visible with --verbose.

🤖 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 `@crates/mesh-llm-commands/src/setup/summary.rs` around lines 166 - 176, The
compact GitHub summary in github_brief is dropping CliUnavailable and
NotAuthenticated into the default None case, so those actionable states never
appear in the non-verbose output. Update github_brief to handle these
SetupGitHubOutcome variants explicitly and return a visible status string,
matching the pattern used by service_brief so the compact "GitHub" line always
reports that setup was not performed or not recorded.

143-164: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Fragile string-literal comparison for service status.

report.summary == "installed and started" couples UI status coloring to a display string owned by service.rs. A future wording change there would silently downgrade a successfully running service to a "start manually" warning with no compiler signal.

Consider adding an explicit status field/variant on ServiceInstallReport (e.g., started: bool or a small enum) and matching on that instead of the rendered summary text.

🤖 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 `@crates/mesh-llm-commands/src/setup/summary.rs` around lines 143 - 164, The
service status logic in service_brief is relying on the display string
report.summary == "installed and started", which is brittle and can silently
misclassify a running service if the wording changes. Update
ServiceInstallReport to carry an explicit status field or enum (for example a
started flag), set it where the report is produced, and change service_brief to
match on that structured value instead of comparing the summary text.
crates/mesh-llm-cli/src/parser/uninstall_tests.rs (1)

34-77: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Missing coverage for --purge-config.

Neither test exercises --purge-config; consider adding an assertion for it alongside the other automation flags in uninstall_accepts_automation_flags.

🤖 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 `@crates/mesh-llm-cli/src/parser/uninstall_tests.rs` around lines 34 - 77, The
uninstall parser test is missing coverage for the `--purge-config` flag, so
update `uninstall_accepts_automation_flags` to include that option in the
`Cli::parse_from` inputs and assert the `purge_config` field from
`Command::Uninstall` is set correctly alongside the existing flags. Use the
`Cli::parse_from` and `Command::Uninstall` destructuring in this test to locate
the change.
crates/mesh-llm-commands/src/uninstall.rs (1)

176-181: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

--purge-config combined with --keep-config silently no-ops.

When both flags are set, the config/identity removal step is simply omitted with no warning, which may surprise a user who explicitly asked to purge. A safe default is fine, but consider warning when the flags conflict.

🤖 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 `@crates/mesh-llm-commands/src/uninstall.rs` around lines 176 - 181, In
uninstall.rs, the UninstallStep::RemovePath branch inside the purge-config
handling silently skips removal when options.purge_config and
options.keep_config are both set. Update the uninstall flow to detect this flag
conflict in the main option-processing logic and emit a warning using the
existing logging/reporting path before continuing with the safe default, so
users of --purge-config and --keep-config get explicit feedback instead of a
silent no-op.
install.ps1 (1)

196-207: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

PowerShell will silently drop the backtick-quoting around mesh-llm.exe setup.

In Write-FlavorCompatibilityWarning (and the matching text in Show-Usage), the message uses `mesh-llm.exe setup` inside a double-quoted string / here-string. A backtick followed by an unrecognized escape character (here m and a space) is not a documented PowerShell escape sequence, so the backtick is dropped rather than rendering literally — the intended "code-style" quoting around the command will not appear in the actual warning/help text.

✏️ Proposed fix
-    Write-Warning "Ignoring legacy -Flavor '$legacyFlavor'. The Windows installer now always installs the x64 host binary; run `mesh-llm.exe setup` to choose the recommended runtime."
+    Write-Warning "Ignoring legacy -Flavor '$legacyFlavor'. The Windows installer now always installs the x64 host binary; run ``mesh-llm.exe setup`` to choose the recommended runtime."

Use doubled backticks (``) to emit a literal backtick, or switch to single quotes around the phrase.

Also applies to: 44-51

🤖 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 `@install.ps1` around lines 196 - 207, The warning/help text in
Write-FlavorCompatibilityWarning and Show-Usage is losing the intended literal
backticks around mesh-llm.exe setup because PowerShell treats the single
backtick as an escape. Update those message strings to use literal backticks
correctly, either by doubling the backticks or by changing the surrounding
quoting so the command renders exactly as code-style text in the final output.
🤖 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 `@crates/mesh-llm-commands/src/terminal.rs`:
- Around line 31-54: The confirmation prompt in the terminal input loop
currently treats EOF as an empty reply, which can incorrectly accept the default
choice. Update the reply handling in the prompt function that reads from stdin
so EOF from read_line is detected before matching the trimmed input, and return
a decline/cancel result instead of calling default.empty_reply(). Keep the
existing y/yes and n/no behavior unchanged.

In `@crates/mesh-llm-commands/src/uninstall.rs`:
- Around line 359-377: In schedule_windows_deferred_binary_delete, the
PowerShell invocation is not actually passing the target path through $args
because the trailing -- and path are being folded into the command string. Fix
the Command::new("powershell.exe") call so the binary path is embedded safely
into the PowerShell script itself, or switch to a script file approach, and
ensure Remove-Item -LiteralPath targets the actual exe rather than $args[0].

In `@crates/mesh-llm/src/commands/setup.rs`:
- Around line 50-57: The current_setup_platform function silently maps every
unknown OS to SetupPlatform::Linux, which can send unsupported hosts down the
wrong setup path. Update current_setup_platform to fail fast for
non-linux/macos/windows targets by returning an explicit unsupported-OS error
instead of defaulting to Linux, and adjust the callers in setup.rs to handle
that error path cleanly.

In `@docs/specs/mesh-setup-installer.md`:
- Around line 27-35: Update the installer spec in the section describing
`install.sh` and `install.ps1` to explicitly document checksum fallback
behavior: when a `.sha256` sidecar is missing, the default behavior should be to
warn and continue, and the install should fail closed only if
`MESH_LLM_REQUIRE_CHECKSUM=1` is set. Keep the wording alongside the existing
checksum verification and archive download bullets so the behavior is clear in
the installer flow.

In `@install.sh`:
- Around line 221-231: The platform_asset_name() helper is currently unused, so
either remove it if it is dead code or connect it to the install flow where the
asset name is needed. Check the install.sh logic around platform_id and any
download/extraction path to see whether platform_asset_name() should be invoked
there. If it is intended for a separate path, add a brief comment and the call
site; otherwise delete the function to avoid unused code.

In `@website/src/_includes/components/cta-terminal.njk`:
- Around line 19-29: The CTA copy in cta-terminal.njk overstates Windows support
because the visible install/setup flow only shows shell commands. Update the
platform wording in the terminal card to scope it to macOS/Linux, or add a
Windows-specific PowerShell option in the existing install templates and display
logic so the claim matches the actual commands shown.

---

Duplicate comments:
In `@crates/mesh-llm-commands/src/setup/service_templates.rs`:
- Around line 25-40: The generated systemd unit in render_systemd_unit leaves
service_env_file unescaped in EnvironmentFile=, so systemd specifier expansion
can misread literals like %. Update render_systemd_unit to apply the same
systemd-safe escaping used elsewhere in this file (for example the escaping
pattern already used by render_service_runner/render_launchd_plist) before
writing EnvironmentFile=-{service_env_file}, while keeping ExecStart handling
unchanged.

---

Nitpick comments:
In `@crates/mesh-llm-cli/src/parser/uninstall_tests.rs`:
- Around line 34-77: The uninstall parser test is missing coverage for the
`--purge-config` flag, so update `uninstall_accepts_automation_flags` to include
that option in the `Cli::parse_from` inputs and assert the `purge_config` field
from `Command::Uninstall` is set correctly alongside the existing flags. Use the
`Cli::parse_from` and `Command::Uninstall` destructuring in this test to locate
the change.

In `@crates/mesh-llm-commands/src/setup/command.rs`:
- Line 54: The initialization of CliSetupActions in command.rs appears to exceed
rustfmt’s preferred width. Reformat the statement in the setup command so it
stays within the standard Rust formatting limits, and then run rustfmt on the
touched Rust code to ensure the command module remains consistently formatted.

In `@crates/mesh-llm-commands/src/setup/github_runner.rs`:
- Around line 113-138: The timeout handling in the GitHub runner loop can
misclassify a process that exits right as the deadline is hit. In the
`run`/polling loop around `child.try_wait()`, add a final `try_wait()` check
inside the `started_at.elapsed() >= self.timeout` branch before calling
`child.kill()`, and only kill if the child is still running; this should keep
`GhCommandError::TimedOut`, `KillFailed`, and the `GhCommandOutput` flow aligned
with the actual process state.

In `@crates/mesh-llm-commands/src/setup/service_files.rs`:
- Around line 8-22: ensure_service_env_file has a TOCTOU race because it checks
Path::exists() before writing, so concurrent invocations can both pass the check
and then overwrite or race on the same env file. Update ensure_service_env_file
to make file creation atomic by using a create-if-missing approach or handling
the already-exists case at write time, while keeping the parent-directory setup
and render_service_env_file flow intact.

In `@crates/mesh-llm-commands/src/setup/service_tests.rs`:
- Around line 66-73: Add coverage in service_tests around render_systemd_unit to
exercise a service_env_file path containing % so we lock in
systemd-specifier-safe escaping for EnvironmentFile=. Mirror the style of the
existing launchd escape tests, but target render_systemd_unit and verify the
generated unit contains the properly escaped EnvironmentFile value rather than
the raw path.

In `@crates/mesh-llm-commands/src/setup/summary.rs`:
- Around line 166-176: The compact GitHub summary in github_brief is dropping
CliUnavailable and NotAuthenticated into the default None case, so those
actionable states never appear in the non-verbose output. Update github_brief to
handle these SetupGitHubOutcome variants explicitly and return a visible status
string, matching the pattern used by service_brief so the compact "GitHub" line
always reports that setup was not performed or not recorded.
- Around line 143-164: The service status logic in service_brief is relying on
the display string report.summary == "installed and started", which is brittle
and can silently misclassify a running service if the wording changes. Update
ServiceInstallReport to carry an explicit status field or enum (for example a
started flag), set it where the report is produced, and change service_brief to
match on that structured value instead of comparing the summary text.

In `@crates/mesh-llm-commands/src/uninstall.rs`:
- Around line 176-181: In uninstall.rs, the UninstallStep::RemovePath branch
inside the purge-config handling silently skips removal when
options.purge_config and options.keep_config are both set. Update the uninstall
flow to detect this flag conflict in the main option-processing logic and emit a
warning using the existing logging/reporting path before continuing with the
safe default, so users of --purge-config and --keep-config get explicit feedback
instead of a silent no-op.

In `@install.ps1`:
- Around line 196-207: The warning/help text in Write-FlavorCompatibilityWarning
and Show-Usage is losing the intended literal backticks around mesh-llm.exe
setup because PowerShell treats the single backtick as an escape. Update those
message strings to use literal backticks correctly, either by doubling the
backticks or by changing the surrounding quoting so the command renders exactly
as code-style text in the final output.
🪄 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: CHILL

Plan: Pro Plus

Run ID: 07546f7b-7cff-43a1-825d-71847bcc839e

📥 Commits

Reviewing files that changed from the base of the PR and between 232c85a and 9f50114.

📒 Files selected for processing (54)
  • README.md
  • crates/mesh-llm-cli/src/parser.rs
  • crates/mesh-llm-cli/src/parser/setup_tests.rs
  • crates/mesh-llm-cli/src/parser/uninstall_tests.rs
  • crates/mesh-llm-commands/src/lib.rs
  • crates/mesh-llm-commands/src/runtime_native.rs
  • crates/mesh-llm-commands/src/runtime_native/setup_helpers.rs
  • crates/mesh-llm-commands/src/setup/actions.rs
  • crates/mesh-llm-commands/src/setup/cli_actions_tests.rs
  • crates/mesh-llm-commands/src/setup/command.rs
  • crates/mesh-llm-commands/src/setup/command_tests.rs
  • crates/mesh-llm-commands/src/setup/environment.rs
  • crates/mesh-llm-commands/src/setup/github.rs
  • crates/mesh-llm-commands/src/setup/github_runner.rs
  • crates/mesh-llm-commands/src/setup/github_tests.rs
  • crates/mesh-llm-commands/src/setup/mod.rs
  • crates/mesh-llm-commands/src/setup/orchestration_tests.rs
  • crates/mesh-llm-commands/src/setup/plan.rs
  • crates/mesh-llm-commands/src/setup/planner.rs
  • crates/mesh-llm-commands/src/setup/prompt.rs
  • crates/mesh-llm-commands/src/setup/service.rs
  • crates/mesh-llm-commands/src/setup/service_files.rs
  • crates/mesh-llm-commands/src/setup/service_paths.rs
  • crates/mesh-llm-commands/src/setup/service_runner.rs
  • crates/mesh-llm-commands/src/setup/service_templates.rs
  • crates/mesh-llm-commands/src/setup/service_tests.rs
  • crates/mesh-llm-commands/src/setup/summary.rs
  • crates/mesh-llm-commands/src/setup/test_support.rs
  • crates/mesh-llm-commands/src/setup/tests.rs
  • crates/mesh-llm-commands/src/terminal.rs
  • crates/mesh-llm-commands/src/uninstall.rs
  • crates/mesh-llm/src/commands/discover.rs
  • crates/mesh-llm/src/commands/mod.rs
  • crates/mesh-llm/src/commands/runtime.rs
  • crates/mesh-llm/src/commands/setup.rs
  • docs/CLI.md
  • docs/README.md
  • docs/USAGE.md
  • docs/specs/mesh-setup-installer.md
  • install.ps1
  • install.sh
  • scripts/tests/test_generate_native_runtime_release_manifest.py
  • scripts/tests/test_install_ps1.py
  • scripts/tests/test_install_sh.py
  • website/src/_includes/components/cta-terminal.njk
  • website/src/_includes/sections/hero.njk
  • website/src/docs/pages/CLI.md
  • website/src/docs/pages/hardware-support.md
  • website/src/docs/pages/installing-linux.md
  • website/src/docs/pages/installing-macos.md
  • website/src/docs/pages/installing-mesh.md
  • website/src/docs/pages/installing-windows.md
  • website/src/docs/pages/quickstart.md
  • website/src/docs/pages/troubleshooting.md

Comment thread crates/mesh-llm-commands/src/terminal.rs
Comment thread crates/mesh-llm-commands/src/uninstall.rs
Comment thread crates/mesh-llm/src/commands/setup.rs Outdated
Comment thread docs/specs/mesh-setup-installer.md
Comment thread install.sh Outdated
Comment thread website/src/_includes/components/cta-terminal.njk Outdated
@github-actions github-actions Bot removed the stale label Jul 8, 2026
@ndizazzo
ndizazzo force-pushed the feature/revise-install-paths branch from 9f0435b to 61441b7 Compare July 10, 2026 10:50
@ndizazzo
ndizazzo merged commit 36a44b9 into main Jul 10, 2026
22 checks passed
@ndizazzo
ndizazzo deleted the feature/revise-install-paths branch July 10, 2026 11:13
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.

install.sh: checksum verification fails on default Ubuntu (mawk)

1 participant