fix(onboard): install daemon by default + OS-aware manage/restart hints#1493
Conversation
Two small UX wins layered on top of PR #1491's prompt-reduction work: 1) Remove the last inline yes/no question --------------------------------------- Before: Install as background service (daemon)? [y/n] (y): _ 95% of users pressed Enter. Non-developers didn't know what 'daemon' meant. If we install by default and they change their mind, 'praisonai gateway uninstall' removes it in one command. So: install silently, no prompt. This finishes the goal of the previous PR: the only questions that remain in 'praisonai onboard' are the three that genuinely need a user answer — platform, token, and allowlist. 2) Tell users how to manage / restart / re-onboard the daemon ----------------------------------------------------------- The old Done panel showed 'praisonai bot start' (foreground) and 'praisonai gateway status'. That answered 'is it running?' but not 'how do I restart / stop / re-run the wizard?'. New panel groups the commands by intent and emits the correct restart line for the platform detected at runtime: Manage the daemon: praisonai gateway status # is it running? praisonai gateway logs # tail the logs launchctl kickstart -k gui/$(id -u)/ai.praison.bot # macOS systemctl --user restart ai.praison.bot # Linux praisonai gateway uninstall # remove the daemon Re-run or reconfigure: praisonai onboard # change tokens / add platforms praisonai gateway start # run in foreground (skip daemon) praisonai doctor # diagnose the whole stack The launchd label ('ai.praison.bot') is the one defined in praisonai/daemon/launchd.py LABEL. Commands and subcommands referenced above were validated against 'praisonai --help' + 'praisonai gateway --help' before shipping. 3) Plain-flow parity ------------------ The non-rich fallback (_run_plain) also now installs the daemon by default and prints the same 4-line next-steps block so terminals without rich aren't stuck with a bare 'Start with: …'. Validation: - The only 'Confirm.ask' call still in wizard.run() is the 'Overwrite with fresh config?' guard from PR #1491. - 9/9 existing onboard tests pass. - Smoke-tested install against the live daemon on macOS — plist regenerated, 'praisonai gateway status' reports healthy. Note on the 'start daemon' question: 'praisonai gateway start' runs the gateway in the FOREGROUND. The daemon auto-starts it in the background via launchd/systemd (the plist's ProgramArguments is literally 'praisonai gateway start --config $abs_config'). The new panel makes this distinction explicit so users don't double-start the server.
There was a problem hiding this comment.
MervinPraison has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.
📝 WalkthroughWalkthroughOnboardWizard now installs the gateway daemon automatically when tokens are present (no interactive install prompt). Added an idempotent install helper, OS-aware restart/uninstall commands, and updated final onboarding output (rich and plain) to show daemon management and reconfiguration steps. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant OnboardWizard
participant DaemonManager
participant OS
User->>OnboardWizard: run onboarding
OnboardWizard->>OnboardWizard: validate/capture tokens
OnboardWizard->>DaemonManager: get_daemon_status()
DaemonManager-->>OnboardWizard: status (installed|not)
alt not installed
OnboardWizard->>DaemonManager: install_daemon(config_path)
DaemonManager-->>OnboardWizard: install result
end
OnboardWizard->>OS: generate OS-specific commands (restart/status/log/uninstall)
OnboardWizard-->>User: print Done panel with daemon management & next steps
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
|
@copilot Do a thorough review of this PR. Read ALL existing reviewer comments above from Qodo, Coderabbit, and Gemini first — incorporate their findings. Review areas:
|
There was a problem hiding this comment.
Code Review
This pull request automates the background service (daemon) installation during the onboarding process, removing the user prompt to simplify the experience. It also introduces OS-aware management commands in the final setup panel. Feedback highlights a mismatch in the Linux service name, a logic error in token detection for the plain-text flow, and a documentation error regarding service labels across platforms.
| if _os == "darwin": | ||
| _restart_cmd = "launchctl kickstart -k gui/$(id -u)/ai.praison.bot" | ||
| elif _os == "linux": | ||
| _restart_cmd = "systemctl --user restart ai.praison.bot" |
There was a problem hiding this comment.
The service name for Linux is defined as praisonai-bot in src/praisonai/praisonai/daemon/systemd.py. Providing the hint with ai.praison.bot will result in a "unit not found" error when the user attempts to run the suggested command on Linux.
| _restart_cmd = "systemctl --user restart ai.praison.bot" | |
| _restart_cmd = "systemctl --user restart praisonai-bot" |
|
|
||
| # Parity with rich flow: install daemon by default (no prompt) | ||
| # when every selected platform has a token captured. | ||
| if self.selected_platforms and all(p in self.tokens for p in self.selected_platforms): |
There was a problem hiding this comment.
In _run_plain, self.tokens is only populated when a user enters a new token during the session. If tokens are already present in the environment, they are skipped in the input loop (lines 580-590), which means all(p in self.tokens ...) will evaluate to False. This prevents the automatic daemon installation for users who already have their environment variables set. Checking os.environ directly ensures the daemon is installed whenever the required tokens are available.
| if self.selected_platforms and all(p in self.tokens for p in self.selected_platforms): | |
| if self.selected_platforms and all(os.environ.get(PLATFORMS.get(p, {}).get("token_env", f"{p.upper()}_BOT_TOKEN")) for p in self.selected_platforms): |
| # line for their platform. Label ``ai.praison.bot`` is defined in | ||
| # praisonai.daemon.launchd / systemd. |
There was a problem hiding this comment.
The comment incorrectly states that ai.praison.bot is used for both launchd and systemd. While this is true for macOS (launchd), the systemd implementation in src/praisonai/praisonai/daemon/systemd.py defines the service name as praisonai-bot.
| # line for their platform. Label ``ai.praison.bot`` is defined in | |
| # praisonai.daemon.launchd / systemd. | |
| # line for their platform. Label ``ai.praison.bot`` is used for launchd, | |
| # while ``praisonai-bot`` is used for systemd. |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/praisonai/praisonai/cli/features/onboard.py`:
- Around line 531-538: The fallback restart logic sets _restart_cmd to an
uninstall+install sequence for non-darwin/linux which is inappropriate for
Windows and cmd.exe; change the platform branch to explicitly check for _os ==
"windows" and set _restart_cmd to a proper Windows task restart (e.g., use
schtasks /End and schtasks /Run or a single command to re-run the scheduled task
managed by daemon/windows.py) or a clear instruction to re-run the installer
(e.g., "re-run 'praisonai gateway install'") so users on Windows do not get a
misleading uninstall/install with shell-operator semantics; update the platform
check around _restart_cmd in onboard.py (and reference daemon/windows.py task
name if needed) accordingly.
- Around line 497-516: The onboarding flow currently calls install_daemon()
unconditionally which is not idempotent and causes failures on rerun; update the
logic to first detect or ensure idempotence: either call a new
praisonai.daemon.is_installed()/reinstall_daemon() before invoking
install_daemon(), or make the platform-specific installers (launchd.install and
systemd.install) idempotent (unload/bootout before load, or use systemctl
restart instead of start) so repeated installs succeed; also persist the install
result from install_daemon() and use it to conditionally show or suppress the
Done panel message ("Your bot is now running in the background.") when
result.get("ok") is false or an exception occurred.
- Around line 614-626: The daemon-install guard in _run_plain incorrectly
requires platforms to be present in self.tokens (which stays empty when tokens
come from env vars), so change the condition to consider either self.tokens or
existing environment variables: e.g., replace all(p in self.tokens for p in
self.selected_platforms) with a check that for each platform p either p is in
self.tokens or os.environ.get(env var name for p) is set; then call
praisonai.daemon.install_daemon(config_path=str(cfg_path)) when that combined
condition is true and preserve the existing try/except feedback logic. Also
extract the duplicate logic into a helper (e.g.,
_install_daemon_with_feedback(print_fn, config_path) or similarly named) and use
it from both _run_plain and the rich-path section to keep behavior and messages
in sync.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: d292d149-56c7-4c05-a461-c6cc48d315bd
📒 Files selected for processing (1)
src/praisonai/praisonai/cli/features/onboard.py
Reviewed at commit Findings:
Suggested improvements (optional, follow-up):
# assert restart command switches by OS
monkeypatch.setattr(platform, "system", lambda: "Linux")
... assert "systemctl --user restart ai.praison.bot" in output# assert daemon install is attempted by default when tokens are complete
mock_install = mocker.patch("praisonai.daemon.install_daemon", return_value={"ok": True})
... wizard.run(...)
mock_install.assert_called_once()
No code changes were needed in this pass. No UI changes in this follow-up, so no screenshot was produced. |
|
@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAI (not a fork), you are able to make modifications to this branch and push directly. SCOPE: Focus ONLY on Python packages (praisonaiagents, praisonai). Do NOT modify praisonai-rust or praisonai-ts. Read ALL comments above from Gemini, Qodo, CodeRabbit, and Copilot carefully before responding. Phase 1: Review per AGENTS.md
Phase 2: FIX Valid Issues Phase 3: Final Verdict |
|
Claude finished @MervinPraison's task —— View job Final Architecture Review ✅Phase 1: Architecture Review per AGENTS.md
Phase 2: Fix Valid Issues
Phase 3: Final Verdict
Architecture Review Results✅ Protocol-driven compliance: This is a wrapper feature (CLI/daemon management) - correctly placed in ✅ Backward compatibility: No breaking API changes. The change removes a yes/no prompt but maintains same config output. ✅ Performance: No hot-path regressions. Only adds a single Issues Found & Fixed ✅All 4 critical issues from reviewer feedback have been fixed in commit
Additional Improvements Made
Final Verdict: APPROVED ✅This PR is ready for merge. All blocking issues identified by reviewers have been resolved. The implementation:
The auto-install daemon behavior with OS-aware management hints is a solid UX improvement that reduces onboarding friction while providing clear next steps for users. |
… token detection - Fix Linux service name mismatch (ai.praison.bot -> praisonai-bot) - Add Windows-specific restart command (schtasks instead of shell operators) - Fix token detection in plain flow for existing environment variables - Make daemon install idempotent by checking status first - Extract duplicate daemon install logic into helper method - Adjust Done panel text based on daemon install success Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
There was a problem hiding this comment.
MervinPraison has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Updates onboarding to install the gateway daemon by default (removing the final yes/no prompt) and improves post-setup guidance with OS-specific daemon management hints, including bringing the plain (non-rich) flow into parity.
Changes:
- Remove the “install daemon?” prompt and install the daemon by default when tokens are present.
- Expand the rich “✅ Done” panel with OS-aware restart guidance and clearer “foreground vs daemon” commands.
- Update the plain flow to auto-install the daemon (when appropriate) and print multi-line next steps.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if _os == "darwin": | ||
| _restart_cmd = "launchctl kickstart -k gui/$(id -u)/ai.praison.bot" | ||
| elif _os == "linux": | ||
| _restart_cmd = "systemctl --user restart praisonai-bot" | ||
| elif _os == "windows": |
There was a problem hiding this comment.
The Done panel prints the full gateway auth token in a URL query string. This is sensitive and can easily leak via terminal scrollback, logs, screenshots, or support copy-paste. Prefer not to print the token at all (or print a placeholder like token=… / token=<GATEWAY_AUTH_TOKEN>), and keep the token value masked consistently.
| console.print(Panel( | ||
| f"[bold green]Setup complete![/bold green]\n\n" | ||
| f"[bold green]Setup complete![/bold green] " |
There was a problem hiding this comment.
This message asserts the bot is running in the background even if install_daemon(...) fails (or if it wasn’t invoked due to earlier branches). Consider making this conditional on result.get('ok'), or soften the wording (e.g., 'If installed, it will run in the background') and/or include an explicit next-step install command on failure.
| _restart_cmd = "schtasks /End /TN PraisonAIGateway && schtasks /Run /TN PraisonAIGateway" | ||
| else: | ||
| _restart_cmd = "praisonai gateway install # re-run installer" | ||
| # Adjust headline based on daemon install success | ||
| daemon_running_text = ( | ||
| "Your bot is now running in the background." if daemon_success | ||
| else "Configuration complete." | ||
| ) |
There was a problem hiding this comment.
The fallback restart command uses && and an uninstall/install sequence, which is not a reliable 'restart' across shells (especially on Windows) and may have side effects (e.g., removing service state). Prefer either omitting the restart line on unsupported OSes, printing two separate commands (uninstall then install) without shell chaining, or providing a CLI-level command for restart (if available) to keep the guidance portable.
| f"[bold]Re-run or reconfigure:[/bold]\n" | ||
| f" [cyan]praisonai onboard[/cyan] [dim]# change tokens / add platforms[/dim]\n" | ||
| f" [cyan]praisonai gateway start[/cyan] [dim]# run in foreground (skip the daemon)[/dim]\n" |
There was a problem hiding this comment.
In the rich Done panel, the suggested foreground command omits --config ..., but the daemon install (and the plain-flow next steps) are tied to a specific config path. If self.config_path can be non-default, users may start the gateway with the wrong config. Consider including the actual config path here (similar to the plain-flow output) for correctness and parity.
| _restart_cmd = "schtasks /End /TN PraisonAIGateway && schtasks /Run /TN PraisonAIGateway" | ||
| else: | ||
| _restart_cmd = "praisonai gateway install # re-run installer" | ||
| # Adjust headline based on daemon install success | ||
| daemon_running_text = ( | ||
| "Your bot is now running in the background." if daemon_success | ||
| else "Configuration complete." | ||
| ) |
There was a problem hiding this comment.
New OS-conditional behavior is introduced here, but the PR notes existing tests pass unchanged. Add unit tests that mock platform.system() to cover the Darwin/Linux/other branches and assert the emitted guidance (and/or the chosen restart command) is correct. This helps prevent regressions in the Done panel content across platforms.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
src/praisonai/praisonai/cli/features/onboard.py (1)
571-580:⚠️ Potential issue | 🟠 MajorRestart or reload an already-running daemon after reconfiguration.
This early return makes repeat onboarding look successful, but the running daemon will keep its old process environment/config after
bot.yamland.envwere just rewritten. Users followingpraisonai onboardto “change tokens / add platforms” may not see changes take effect until they manually restart.Either restart the existing service here, or return a distinct “restart required” state and make the Done panel call that out.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/praisonai/praisonai/cli/features/onboard.py` around lines 571 - 580, The current early return in the onboard flow skips restarting/reloading a running daemon after bot.yaml/.env changes; locate the block using get_daemon_status() and install_daemon(config_path=...) and either (A) call a restart/reload on the running daemon (e.g., expose/use a restart_daemon or install_daemon(force_restart=True) path so the running service picks up the new config) or (B) change the return to a distinct "restart_required" state instead of True and update the caller/Done panel to surface that restart is needed; ensure the chosen approach references get_daemon_status, install_daemon and the print_fn message so users see the action taken.
🧹 Nitpick comments (1)
src/praisonai/praisonai/cli/features/onboard.py (1)
591-592: Narrow or explicitly justify this broad catch.
get_daemon_status()/install_daemon()already return error dicts for expected daemon failures, so this blanket catch can mask programming errors. If keeping it for UX, add a# noqa: BLE001with a short rationale.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/praisonai/praisonai/cli/features/onboard.py` around lines 591 - 592, The broad except Exception in the onboard flow (around the call sites for get_daemon_status() / install_daemon() where print_fn prints the error) should be narrowed or explicitly justified: either catch specific expected exceptions (e.g., DaemonInstallError, DaemonStatusError, OSError) and let other exceptions propagate, or if you must retain a catch-all for UX, add a single-line `# noqa: BLE001` with a short rationale comment above it and re-raise unexpected exceptions after logging (or log the full traceback) so programming errors aren't silently swallowed; update the handler that currently does print_fn(f" ✗ {str(e)[:200]}") accordingly and reference get_daemon_status()/install_daemon() in your change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/praisonai/praisonai/cli/features/onboard.py`:
- Around line 519-548: The printed _info_url currently includes the full
GATEWAY_AUTH_TOKEN (via _tok) and must not be rendered; update the
console.print/Panel output to show the info endpoint without including the token
(use the base URL like "http://127.0.0.1:8765/info" or a placeholder such as
"http://127.0.0.1:8765/info?token=<REDACTED>") and remove any interpolation of
_tok into the displayed string, while keeping the existing note that the token
(_masked) is stored in ~/.praisonai/.env as GATEWAY_AUTH_TOKEN so users know
where to find it; adjust references to _info_url, _tok and _masked accordingly
in the Panel format string.
- Around line 646-660: The plain-flow next-steps always assume the daemon was
installed; change this to branch based on the daemon-install check and outcome:
reuse the token presence condition around self.selected_platforms and tokens/env
to decide whether to attempt install, call
self._install_daemon_with_feedback(print, str(cfg_path)) and capture its
success/failure, and then print different “Next steps” text depending on whether
the daemon was installed, skipped (tokens missing) or failed, mirroring the rich
flow’s skip/feedback behavior; update the block that currently prints the Next
steps after the token check to conditionally print daemon-first commands only
when install succeeded, otherwise print instructions for adding tokens and
starting in foreground.
---
Duplicate comments:
In `@src/praisonai/praisonai/cli/features/onboard.py`:
- Around line 571-580: The current early return in the onboard flow skips
restarting/reloading a running daemon after bot.yaml/.env changes; locate the
block using get_daemon_status() and install_daemon(config_path=...) and either
(A) call a restart/reload on the running daemon (e.g., expose/use a
restart_daemon or install_daemon(force_restart=True) path so the running service
picks up the new config) or (B) change the return to a distinct
"restart_required" state instead of True and update the caller/Done panel to
surface that restart is needed; ensure the chosen approach references
get_daemon_status, install_daemon and the print_fn message so users see the
action taken.
---
Nitpick comments:
In `@src/praisonai/praisonai/cli/features/onboard.py`:
- Around line 591-592: The broad except Exception in the onboard flow (around
the call sites for get_daemon_status() / install_daemon() where print_fn prints
the error) should be narrowed or explicitly justified: either catch specific
expected exceptions (e.g., DaemonInstallError, DaemonStatusError, OSError) and
let other exceptions propagate, or if you must retain a catch-all for UX, add a
single-line `# noqa: BLE001` with a short rationale comment above it and
re-raise unexpected exceptions after logging (or log the full traceback) so
programming errors aren't silently swallowed; update the handler that currently
does print_fn(f" ✗ {str(e)[:200]}") accordingly and reference
get_daemon_status()/install_daemon() in your change.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: e5d762e1-dde8-400d-a34a-54310edbeaeb
📒 Files selected for processing (1)
src/praisonai/praisonai/cli/features/onboard.py
| _info_url = ( | ||
| f"http://127.0.0.1:8765/info?token={_tok}" | ||
| if _tok | ||
| else "http://127.0.0.1:8765/info" | ||
| ) | ||
| import platform as _platform # stdlib, free | ||
| _os = _platform.system().lower() | ||
| if _os == "darwin": | ||
| _restart_cmd = "launchctl kickstart -k gui/$(id -u)/ai.praison.bot" | ||
| elif _os == "linux": | ||
| _restart_cmd = "systemctl --user restart praisonai-bot" | ||
| elif _os == "windows": | ||
| _restart_cmd = "schtasks /End /TN PraisonAIGateway && schtasks /Run /TN PraisonAIGateway" | ||
| else: | ||
| _restart_cmd = "praisonai gateway install # re-run installer" | ||
| # Adjust headline based on daemon install success | ||
| daemon_running_text = ( | ||
| "Your bot is now running in the background." if daemon_success | ||
| else "Configuration complete." | ||
| ) | ||
|
|
||
| console.print(Panel( | ||
| f"[bold green]Setup complete![/bold green]\n\n" | ||
| f"[bold green]Setup complete![/bold green] " | ||
| f"[dim]{daemon_running_text}[/dim]\n\n" | ||
| f"[bold]🦞 Dashboard UI:[/bold]\n" | ||
| f" [cyan]praisonai claw[/cyan] [dim]→ http://127.0.0.1:8082[/dim]\n\n" | ||
| f"[bold]Start your bot (foreground):[/bold]\n" | ||
| f" [cyan]praisonai bot start[/cyan]\n\n" | ||
| f"[bold]Gateway endpoints:[/bold]\n" | ||
| f" Health (public): [cyan]{_health_url}[/cyan]\n" | ||
| f" Info (authed): [cyan]{_info_url}[/cyan]\n" | ||
| f" [dim]Token {_masked} stored in ~/.praisonai/.env as GATEWAY_AUTH_TOKEN[/dim]\n\n" |
There was a problem hiding this comment.
Avoid printing the full gateway auth token.
Line 547 exposes GATEWAY_AUTH_TOKEN in the terminal via _info_url, even though Line 548 masks it. Prefer a placeholder URL and tell users the token is stored in ~/.praisonai/.env.
🛡️ Proposed fix
- _info_url = (
- f"http://127.0.0.1:8765/info?token={_tok}"
- if _tok
- else "http://127.0.0.1:8765/info"
- )
+ _info_url = (
+ "http://127.0.0.1:8765/info?token=<GATEWAY_AUTH_TOKEN>"
+ if _tok
+ else "http://127.0.0.1:8765/info"
+ )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/praisonai/praisonai/cli/features/onboard.py` around lines 519 - 548, The
printed _info_url currently includes the full GATEWAY_AUTH_TOKEN (via _tok) and
must not be rendered; update the console.print/Panel output to show the info
endpoint without including the token (use the base URL like
"http://127.0.0.1:8765/info" or a placeholder such as
"http://127.0.0.1:8765/info?token=<REDACTED>") and remove any interpolation of
_tok into the displayed string, while keeping the existing note that the token
(_masked) is stored in ~/.praisonai/.env as GATEWAY_AUTH_TOKEN so users know
where to find it; adjust references to _info_url, _tok and _masked accordingly
in the Panel format string.
| # Parity with rich flow: install daemon by default (no prompt) | ||
| # when every selected platform has a token captured. | ||
| if self.selected_platforms and all( | ||
| p in self.tokens or os.environ.get( | ||
| PLATFORMS.get(p, {}).get("token_env", f"{p.upper()}_BOT_TOKEN") | ||
| ) | ||
| for p in self.selected_platforms | ||
| ): | ||
| self._install_daemon_with_feedback(print, str(cfg_path)) | ||
|
|
||
| print("\nNext steps:") | ||
| print(" praisonai gateway status # check if the daemon is running") | ||
| print(" praisonai gateway logs # see what the bot is doing") | ||
| print(" praisonai onboard # change tokens / add platforms") | ||
| print(f" praisonai gateway start --config {cfg_path} # foreground run (no daemon)") |
There was a problem hiding this comment.
Make plain next steps reflect daemon install outcome.
The token check itself looks good, but the plain flow ignores the install result and gives daemon-first next steps even when install failed or was skipped because tokens are missing. Mirror the rich flow’s skip feedback and branch the next steps.
🧭 Proposed adjustment
+ daemon_success = False
+ all_tokens_present = self.selected_platforms and all(
+ p in self.tokens or os.environ.get(
+ PLATFORMS.get(p, {}).get("token_env", f"{p.upper()}_BOT_TOKEN")
+ )
+ for p in self.selected_platforms
+ )
+
# Parity with rich flow: install daemon by default (no prompt)
# when every selected platform has a token captured.
- if self.selected_platforms and all(
- p in self.tokens or os.environ.get(
- PLATFORMS.get(p, {}).get("token_env", f"{p.upper()}_BOT_TOKEN")
- )
- for p in self.selected_platforms
- ):
- self._install_daemon_with_feedback(print, str(cfg_path))
+ if all_tokens_present:
+ daemon_success = self._install_daemon_with_feedback(print, str(cfg_path))
+ else:
+ missing = [
+ PLATFORMS.get(p, {}).get("name", p)
+ for p in self.selected_platforms
+ if p not in self.tokens and not os.environ.get(
+ PLATFORMS.get(p, {}).get("token_env", f"{p.upper()}_BOT_TOKEN")
+ )
+ ]
+ print(f"\n⚠ Skipping daemon install — missing token(s) for: {', '.join(missing)}")
print("\nNext steps:")
- print(" praisonai gateway status # check if the daemon is running")
- print(" praisonai gateway logs # see what the bot is doing")
+ if daemon_success:
+ print(" praisonai gateway status # check if the daemon is running")
+ print(" praisonai gateway logs # see what the bot is doing")
print(" praisonai onboard # change tokens / add platforms")
print(f" praisonai gateway start --config {cfg_path} # foreground run (no daemon)")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/praisonai/praisonai/cli/features/onboard.py` around lines 646 - 660, The
plain-flow next-steps always assume the daemon was installed; change this to
branch based on the daemon-install check and outcome: reuse the token presence
condition around self.selected_platforms and tokens/env to decide whether to
attempt install, call self._install_daemon_with_feedback(print, str(cfg_path))
and capture its success/failure, and then print different “Next steps” text
depending on whether the daemon was installed, skipped (tokens missing) or
failed, mirroring the rich flow’s skip/feedback behavior; update the block that
currently prints the Next steps after the token check to conditionally print
daemon-first commands only when install succeeded, otherwise print instructions
for adding tokens and starting in foreground.
Ask
Validation of terminology
praisonai gateway startpraisonai gateway installpraisonai gateway startin the background withKeepAlive=true.praisonai gateway statuspraisonai gateway uninstallSo: no,
praisonai gateway startis not the daemon command. The plist generated bypraisonai.daemon.launchd(LABEL = 'ai.praison.bot') literally wrapspraisonai gateway start --config ~/.praisonai/bot.yaml. This PR makes the distinction explicit in the Done panel.Fix 1 — drop the last yes/no prompt
Previously the wizard still asked
Install as background service (daemon)? [y/n] (y):. 95% of users pressed Enter; non-developers didn't know what 'daemon' means. Now the daemon installs silently when every selected platform has a token. Users who don't want it runpraisonai gateway uninstall.Onboarding is now zero yes/no prompts once tokens are collected (only the Overwrite-config confirm remains, and only when an existing
bot.yamlis detected).Fix 2 — explain how to manage the daemon
New ✅ Done panel, grouped by intent. The restart line is emitted per-OS using
platform.system()at runtime:Fix 3 — plain-flow parity
Non-rich terminals (where
richisn't available) now also install the daemon by default and print an equivalent 4-line next-steps block. Previously they were stuck with a bareStart with: praisonai bot start --config …line.Verification
tests/unit/cli/test_onboard_security.pypass unchanged.Confirm.ask('Install as background service…')no longer inOnboardWizard.run.Confirm.ask('Overwrite with fresh config?')still present (guards existing files).launchctl kickstart -k gui/$(id -u)/ai.praison.botemitted on macOS.systemctl --user restart ai.praison.botemitted on Linux.praisonai gateway statusreports healthy.Diff
1 file changed, 61 insertions(+), 12 deletions(-)Summary by CodeRabbit