Skip to content

Conversation

@puwun
Copy link
Contributor

@puwun puwun commented Jan 23, 2026

Description

Adds --with-server flag to the CLI mode, allowing users to start the rogue server alongside the CLI in the same command

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)

Changes Made

  • Added --with-server argument to the CLI parser in rogue/__main__.py

Related Issues/PRs

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 23, 2026

Summary by CodeRabbit

  • New Features

    • Added a --with-server option for CLI and TUI to optionally start a background server during your session.
  • Improvements

    • Background server startup now reports failures promptly and cleans up orphaned processes.
    • Sessions ensure the background server is terminated and waited-on after completion for more reliable shutdown behavior.
    • Host normalization for server URLs improved to better handle IPv4, IPv6, and wildcard addresses.
  • Tests

    • Added unit tests covering host normalization behavior for IPv4, IPv6, hostnames, and wildcard addresses.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Adds a --with-server option to CLI and TUI entrypoints to optionally start a background rogue server; implements host normalization for health checks, background server readiness/termination logic, and unit tests for host normalization.

Changes

Cohort / File(s) Summary
Entrypoints (CLI & TUI)
rogue/__main__.py
Added --with-server flag to CLI and TUI parsers; when set, start background server, derive rogue_server_url via host normalization, wire example auto-configuration, enhance error handling, and always terminate/join background server in finally blocks.
Server lifecycle & readiness
rogue/run_server.py
Replaced manual host normalization with get_host_for_url; if background server fails readiness, terminate the orphan process and join (5s) before raising; improved startup failure cleanup.
Network utilities
rogue/common/network.py
New public function get_host_for_url(host: str) -> str that maps wildcard IPs to 127.0.0.1, brackets IPv6 addresses, and leaves hostnames unchanged.
Tests
rogue/tests/common/test_network.py
New unit tests covering IPv4, hostname, wildcard, and IPv6 (including already-bracketed) behavior for get_host_for_url.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Entrypoint as CLI/TUI
    participant ServerStarter
    participant BackgroundServer

    User->>Entrypoint: run command with --with-server
    Entrypoint->>ServerStarter: request start background server (host, port)
    ServerStarter->>BackgroundServer: spawn process
    BackgroundServer-->>ServerStarter: process started (async)
    ServerStarter->>ServerStarter: normalize host (get_host_for_url) and wait for readiness
    alt ready
        ServerStarter-->>Entrypoint: return server URL
        Entrypoint->>Entrypoint: execute CLI/TUI logic (uses server URL)
        Entrypoint->>ServerStarter: request shutdown
        ServerStarter->>BackgroundServer: terminate & join
    else not ready
        ServerStarter->>BackgroundServer: terminate & join (5s timeout)
        ServerStarter-->>Entrypoint: raise startup error
        Entrypoint-->>User: exit with error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • qualifire-dev/rogue#140: Modifies rogue/__main__.py to add/wire a --with-server flag and manage background-server lifecycle — directly related.

Suggested reviewers

  • drorIvry
  • yuval-qf

Poem

🐰 I nudged a flag and set things stirring,
Spawned a server while the CLI was purring,
I bracketed hops through IPv6 lanes,
Nibbled failures, closed loose chains,
Now processes rest as moonlight's blurring.

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% 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
Title check ✅ Passed The title clearly and specifically describes the main feature being added: a --with-server flag for CLI mode, which directly aligns with the primary change.
Description check ✅ Passed The PR description covers the main feature and references the linked issue #80, but lacks comprehensive details about changes to other files and testing information per template.
Linked Issues check ✅ Passed The implementation adds the --with-server CLI argument to both CLI and TUI parsers, enables background server startup in CLI mode with proper error handling, and includes new utility functions and tests as described.
Out of Scope Changes check ✅ Passed All changes are within scope: the new utility function, tests, enhanced error handling, and server cleanup logic all directly support the --with-server feature request.

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

✨ Finishing touches
  • 📝 Generate docstrings

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 and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@rogue/__main__.py`:
- Around line 273-288: The code calls asyncio.run(run_cli(args)) without
catching exceptions, which can leave exit_code undefined and cause
UnboundLocalError later; wrap the asyncio.run(run_cli(args)) call in a
try/except that catches Exception as e, logs the failure via logger.error
(including e), sets exit_code to a non-zero value (e.g., 1), and then let the
finally block terminate/join server_process as before so sys.exit(exit_code)
always has a value; reference run_cli, asyncio.run, exit_code, server_process
and logger in your change.

@puwun puwun force-pushed the feature/cli-with-server branch from dbb4f98 to 14e7614 Compare January 23, 2026 14:15
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@rogue/__main__.py`:
- Around line 273-281: The call to run_server(..., background=True) inside the
args.with_server branch can raise exceptions that bypass the existing
falsy-return check; wrap the run_server call in a try/except that catches
Exception, log the error with logger.error including the exception information,
and call sys.exit(1) on failure (same behavior as the falsy-return case). Ensure
you still assign server_process on success and preserve the existing check for
falsy returns (i.e., if not server_process: logger.error(...); sys.exit(1)) so
both exceptions and false returns are handled.
- Around line 274-285: After starting the background server with
run_server(args, background=True) ensure args.rogue_server_url points at the
actual server address instead of the hardcoded default: update run_server to
return the real URL (or host/port) along with the process (e.g., return
(process, url) or set process.rogue_server_url/process.host/process.port), then
after server_process is assigned set args.rogue_server_url = returned_url (or
build "http://{host}:{port}" from process.host/process.port) before calling
asyncio.run(run_cli(args)); reference run_server, server_process, args and
args.rogue_server_url when making the change.

@puwun puwun force-pushed the feature/cli-with-server branch from 14e7614 to e261213 Compare January 23, 2026 15:14
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@rogue/__main__.py`:
- Around line 274-287: The code sets args.rogue_server_url directly from
args.host which produces a non-routable URL when the server binds to all
interfaces (e.g., "0.0.0.0" or "::"); after run_server and verifying
server_process, detect if args.host is an all-interfaces address and if so
substitute a loopback (e.g., "127.0.0.1" or "localhost") before building
args.rogue_server_url, otherwise use args.host as-is; update the assignment of
args.rogue_server_url accordingly (references: args.rogue_server_url, args.host,
args.port, run_server, server_process).
- Around line 288-293: The try/except around asyncio.run(run_cli(args)) can let
KeyboardInterrupt (and other BaseException subclasses) bypass the Exception
handler and leave exit_code undefined; update the block around asyncio.run in
__main__.py to also catch KeyboardInterrupt (or BaseException) and set exit_code
to a suitable value (e.g., 1), and log via logger.error or logger.warning
including the interrupt info so that sys.exit(exit_code) always has a defined
value; ensure references include asyncio.run, run_cli, exit_code, logger, and
sys.exit(exit_code).

@puwun puwun force-pushed the feature/cli-with-server branch 2 times, most recently from 01578a7 to efcb347 Compare January 23, 2026 16:50
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@rogue/__main__.py`:
- Around line 273-305: The background server spawned by run_server
(rogue/run_server.py) can be orphaned when readiness checks fail and an
exception is raised before the process handle is returned; update run_server to
always clean up the spawned subprocess on readiness failure (terminate/kill and
join) before raising, or change the error path to raise an exception that
includes the process handle so callers (e.g., __main__.py's server_process
variable) can reliably terminate it; modify the failure branch near the
readiness-check code (where the exception is raised around line 148) to perform
process.terminate()/process.kill() and process.join() (or attach the process to
the exception) so __main__.py's try/except can never leave a running orphaned
process.

@puwun puwun force-pushed the feature/cli-with-server branch from efcb347 to 6155bcd Compare January 24, 2026 05:40
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
rogue/__main__.py (1)

313-321: TUI mode is missing exception handling for run_server call.

Unlike the CLI mode (lines 275-282), the TUI mode's run_server call isn't wrapped in a try/except. Since run_server(..., background=True) can raise an Exception("Server failed to start") when readiness checks fail, an unhandled exception will propagate with a traceback instead of a clean error message and exit.

🔧 Suggested fix
             server_process = None
             if args.with_server:
-                server_process = run_server(
-                    args,
-                    background=True,
-                    log_file=log_file_path,
-                )
-                if not server_process:
-                    logger.error("Failed to start rogue server. Exiting.")
+                try:
+                    server_process = run_server(
+                        args,
+                        background=True,
+                        log_file=log_file_path,
+                    )
+                except Exception as e:
+                    logger.error(f"Failed to start rogue server: {e}")
+                    sys.exit(1)
+                if not server_process:
+                    logger.error("Failed to start rogue server. Exiting.")
                     sys.exit(1)
🤖 Fix all issues with AI agents
In `@rogue/__main__.py`:
- Around line 286-291: The URL construction using client_host and
args.rogue_server_url doesn't bracket IPv6 addresses other than "::", producing
invalid URLs like http://::1:8000; update the logic that sets client_host (and
thus args.rogue_server_url) to detect when args.host is an IPv6 address (use the
ipaddress module or reuse the helper from wait_until_server_ready in
run_server.py), and if it's IPv6 wrap the address in [ ] before interpolating
into f"http://{client_host}:{args.port}"; add or move the ipaddress import to
the top of the file if needed.

- Extract get_host_for_url utility
- Fix orphan server process on startup failure
- Auto-configure MCP transport for examples
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.

[Feature] - Add --with-server cli arg to CLI mode

1 participant