diff --git a/README.md b/README.md index eb4184f..4ba83c0 100644 --- a/README.md +++ b/README.md @@ -64,38 +64,19 @@ muxplex ## Install as a Service -### macOS (launchd) - ```bash -# Install and load the launchd agent (auto-starts on login) -muxplex install-service # deprecated — use 'muxplex service install' -launchctl load ~/Library/LaunchAgents/com.muxplex.plist +muxplex service install ``` +The service starts automatically on login (macOS) or at boot (Linux) and restarts on failure. + To stop and remove: -```bash -launchctl unload ~/Library/LaunchAgents/com.muxplex.plist -``` - -### Linux / WSL — User service (no sudo required) ```bash -# Install and enable the user systemd service -muxplex install-service # deprecated — use 'muxplex service install' -systemctl --user daemon-reload -systemctl --user enable --now muxplex +muxplex service uninstall ``` -The service starts automatically when you log in and restarts on failure. - -### Linux — System-wide service (requires sudo) - -```bash -# Install as a system service (runs at boot for all users) -muxplex install-service --system # deprecated — use 'muxplex service install --system' -sudo systemctl daemon-reload -sudo systemctl enable --now muxplex -``` +> **Note:** All service commands use the `muxplex service` subcommand — see [Service management](#service-management) below. --- @@ -125,6 +106,26 @@ All serve options read from `~/.config/muxplex/settings.json` by default. CLI fl | `muxplex reset-secret` | Regenerate signing secret (invalidates sessions) | | `muxplex install-service` | *(deprecated — use `muxplex service install`)* | +### Service management + +```bash +muxplex service install # Write service file + enable + start +muxplex service uninstall # Stop + disable + remove service file +muxplex service start # Start the service +muxplex service stop # Stop the service +muxplex service restart # Stop + start +muxplex service status # Show running/stopped + PID +muxplex service logs # Tail service logs +``` + +The service runs `muxplex serve` with no flags — it reads all options from `~/.config/muxplex/settings.json`. To change host/port, edit the config and restart: + +```bash +# Edit settings to bind to all interfaces +# (or use the Settings UI in the browser) +muxplex service restart +``` + ### Examples ```bash diff --git a/muxplex/tests/test_readme.py b/muxplex/tests/test_readme.py new file mode 100644 index 0000000..d52ca52 --- /dev/null +++ b/muxplex/tests/test_readme.py @@ -0,0 +1,63 @@ +"""Tests for README.md documentation correctness.""" + +from pathlib import Path + +README = (Path(__file__).parent.parent.parent / "README.md").read_text() + + +def test_readme_has_service_management_section(): + """README must have a '### Service management' section.""" + assert "### Service management" in README, ( + "README must contain '### Service management' section" + ) + + +def test_readme_service_management_has_all_7_subcommands(): + """README Service management section must list all 7 subcommands.""" + subcommands = [ + "muxplex service install", + "muxplex service uninstall", + "muxplex service start", + "muxplex service stop", + "muxplex service restart", + "muxplex service status", + "muxplex service logs", + ] + for cmd in subcommands: + assert cmd in README, f"README must mention '{cmd}' in Service management section" + + +def test_readme_explains_settings_json_no_flags(): + """README must explain that the service reads from settings.json with no flags.""" + assert "settings.json" in README, "README must mention settings.json" + # Check that it explains no-flags behavior relative to the service + assert "no flags" in README or "reads all options from" in README, ( + "README must explain that the service reads options from settings.json (no flags)" + ) + + +def test_readme_shows_restart_workflow(): + """README must show a restart workflow example for config changes.""" + assert "muxplex service restart" in README, ( + "README must include 'muxplex service restart' in the example" + ) + + +def test_readme_no_plain_install_service_in_install_sections(): + """README install/setup sections must not use plain 'muxplex install-service' as active command.""" + lines = README.splitlines() + # Find lines that are in bash code blocks and contain install-service without being + # marked deprecated or commented out + in_code_block = False + for i, line in enumerate(lines): + stripped = line.strip() + if stripped.startswith("```"): + in_code_block = not in_code_block + if in_code_block and "install-service" in stripped: + # Allow lines that are comments (# deprecated) or explicitly deprecated + if not stripped.startswith("#"): + # This is an active command — it should NOT be 'muxplex install-service' + assert "muxplex install-service" not in stripped, ( + f"Line {i+1} has active 'muxplex install-service' command in code block: {line!r}. " + "Update to use 'muxplex service install' instead." + )