From 46e8856bfdbc37562504e58266c74bdaa3fb1f8a Mon Sep 17 00:00:00 2001 From: Dennis Dornon Date: Tue, 24 Mar 2026 10:11:06 -0400 Subject: [PATCH 1/2] rename CLI binary from mainwpctl to mainwpcontrol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align the executable name with the product name "MainWP Control" for easier user recall. This is a clean pre-release break (0 users). Changes across 74 files: - package.json: bin, oclif.bin, oclif.dirname, identifier, s3 bucket - All source: mainwpctl→mainwpcontrol, MAINWPCTL→MAINWPCONTROL - Shell completions: file renames + content update - Docs: npx examples fixed to use --package=@mainwp/control form - npm paths corrected to @mainwp/control (was broken before rename) No migration. Testers must re-login after this change. --- .env.example | 2 +- README.md | 80 +++++++++---------- docs/workflows/daily-health-check.md | 46 +++++------ docs/workflows/input-from-file.md | 76 +++++++++--------- docs/workflows/monitoring-integration.md | 60 +++++++------- docs/workflows/monthly-batch-updates.md | 60 +++++++------- .../plugin-deployment-verification.md | 48 +++++------ package-lock.json | 62 +++++++++++--- package.json | 10 +-- scripts/completions/README.md | 32 ++++---- .../{mainwpctl.bash => mainwpcontrol.bash} | 18 ++--- .../{mainwpctl.zsh => mainwpcontrol.zsh} | 58 +++++++------- scripts/completions/profile-completer.sh | 10 +-- scripts/completions/regenerate.sh | 28 +++---- src/__tests__/e2e/command-workflows.test.ts | 6 +- src/__tests__/e2e/exit-codes.test.ts | 6 +- src/__tests__/e2e/json-contract.test.ts | 6 +- .../e2e/login-abilities-flow.test.ts | 4 +- src/__tests__/e2e/non-tty-behavior.test.ts | 12 +-- src/__tests__/process/abilities-info.test.ts | 4 +- src/__tests__/process/abilities-list.test.ts | 4 +- src/__tests__/process/abilities-run.test.ts | 4 +- src/__tests__/process/auth.test.ts | 2 +- src/__tests__/process/batch-wait.test.ts | 2 +- src/__tests__/process/doctor.test.ts | 2 +- src/__tests__/process/exit-codes.test.ts | 4 +- src/__tests__/process/fixtures/cli-runner.ts | 2 +- src/__tests__/process/fixtures/config-dir.ts | 8 +- src/__tests__/process/global-flags.test.ts | 2 +- src/__tests__/process/live-api.test.ts | 4 +- .../process/live-workflow-docs.test.ts | 2 +- src/__tests__/process/scenarios.test.ts | 2 +- src/__tests__/process/smoke.test.ts | 14 ++-- src/chat/chat-engine.test.ts | 2 +- src/chat/chat-engine.ts | 2 +- src/chat/providers/anthropic.ts | 2 +- src/chat/providers/gemini.ts | 2 +- src/chat/providers/local.ts | 2 +- src/chat/providers/openai.ts | 2 +- src/chat/providers/openrouter.ts | 4 +- src/chat/providers/provider.ts | 2 +- src/chat/system-prompt.ts | 2 +- src/chat/tool-envelope.ts | 2 +- src/commands/abilities/info.ts | 4 +- src/commands/abilities/list.ts | 2 +- src/commands/abilities/run.ts | 10 +-- src/commands/chat.ts | 8 +- src/commands/config/show.ts | 6 +- src/commands/doctor.ts | 8 +- src/commands/jobs/watch.ts | 2 +- src/commands/login.ts | 2 +- src/commands/profile/delete.ts | 4 +- src/commands/profile/list.ts | 4 +- src/commands/profile/use.ts | 4 +- src/config/keychain.ts | 8 +- src/config/profile-store.ts | 10 +-- src/config/settings.ts | 8 +- src/core/abilities-executor.ts | 4 +- src/core/batch-manager.ts | 2 +- src/core/http-client.ts | 8 +- src/core/safety-controller.ts | 2 +- src/lib/base-command.ts | 8 +- src/output/formatter.ts | 2 +- src/output/json-envelope.ts | 2 +- src/utils/audit-logger.ts | 4 +- src/utils/colors.ts | 2 +- src/utils/errors.ts | 4 +- src/utils/exit-codes.ts | 2 +- src/utils/format.ts | 2 +- src/utils/prompt.ts | 2 +- src/utils/retry.ts | 2 +- src/utils/terminal-sanitizer.ts | 2 +- src/validation/input-sanitizer.ts | 4 +- src/validation/schema-validator.ts | 4 +- 74 files changed, 438 insertions(+), 400 deletions(-) rename scripts/completions/{mainwpctl.bash => mainwpcontrol.bash} (92%) rename scripts/completions/{mainwpctl.zsh => mainwpcontrol.zsh} (84%) diff --git a/.env.example b/.env.example index a53f410..6060fc0 100644 --- a/.env.example +++ b/.env.example @@ -8,7 +8,7 @@ # Set to 1 to skip loading keytar (OS keychain). Useful in CI/containers # where native modules are unavailable. Falls back to MAINWP_APP_PASSWORD. -# MAINWPCTL_NO_KEYTAR=1 +# MAINWPCONTROL_NO_KEYTAR=1 # ─── Network ───────────────────────────────────────────────────────── # Allow insecure HTTP connections (not recommended for production). diff --git a/README.md b/README.md index c630ef3..5b62a76 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MainWP Control -A CLI for managing your MainWP Dashboard from the terminal. The command is `mainwpctl`. +A CLI for managing your MainWP Dashboard from the terminal. The command is `mainwpcontrol`. You can list sites, check status, push updates, sync data, add or remove child sites, and run batch operations across dozens of sites. Everything outputs structured JSON for piping into other tools. Exit codes are deterministic so CI pipelines can branch on them. There's also an optional chat mode if you want to explore abilities conversationally before scripting them. @@ -10,7 +10,7 @@ You can list sites, check status, push updates, sync data, add or remove child s **[MainWP MCP Server](https://github.com/mainwp/mainwp-mcp)** is for conversational AI management: natural language queries inside Claude, Cursor, ChatGPT, or any MCP-compatible client. Good for exploration, ad-hoc questions, and interactive workflows. -**MainWP Control** is for automation: cron jobs, CI/CD pipelines, monitoring scripts, and batch operations. `mainwpctl` gives you deterministic exit codes, stable JSON output, and composability with standard Unix tools. Both talk to the same Abilities API with the same safety model. +**MainWP Control** is for automation: cron jobs, CI/CD pipelines, monitoring scripts, and batch operations. `mainwpcontrol` gives you deterministic exit codes, stable JSON output, and composability with standard Unix tools. Both talk to the same Abilities API with the same safety model. --- @@ -31,10 +31,10 @@ This is the best path for most users. Pre-built keychain binaries are included f npm install -g @mainwp/control # Log in (stores credentials in your OS keychain) -mainwpctl login +mainwpcontrol login # Verify it works -mainwpctl abilities run list-sites-v1 --json +mainwpcontrol abilities run list-sites-v1 --json ``` ### Option B: Environment variable auth (no keychain) @@ -49,15 +49,15 @@ npm install -g @mainwp/control export MAINWP_APP_PASSWORD='xxxx xxxx xxxx xxxx xxxx xxxx' # Log in non-interactively (credentials stay in the environment, not on disk) -mainwpctl login --url https://dashboard.example.com --username admin +mainwpcontrol login --url https://dashboard.example.com --username admin # Verify it works -mainwpctl abilities run list-sites-v1 --json +mainwpcontrol abilities run list-sites-v1 --json ``` > **Tip:** If keytar is installed but broken, set `MAINWPCTL_NO_KEYTAR=1` to skip loading it entirely. -When the OS keychain is unavailable, `mainwpctl` does not persist plaintext credentials. Keep `MAINWP_APP_PASSWORD` set for each run on CI, cron hosts, and headless servers. +When the OS keychain is unavailable, `mainwpcontrol` does not persist plaintext credentials. Keep `MAINWP_APP_PASSWORD` set for each run on CI, cron hosts, and headless servers. --- @@ -77,7 +77,7 @@ A terminal is where you type commands instead of clicking buttons. You'll see it ### What does `npm install -g` do? -`npm` is the Node.js package manager. It downloads and installs JavaScript packages. The `-g` flag installs globally, which makes `mainwpctl` available as a command anywhere on your system, not only in one project folder. +`npm` is the Node.js package manager. It downloads and installs JavaScript packages. The `-g` flag installs globally, which makes `mainwpcontrol` available as a command anywhere on your system, not only in one project folder. ### What is an environment variable? @@ -92,19 +92,19 @@ export MAINWP_APP_PASSWORD='xxxx xxxx xxxx xxxx xxxx xxxx' $env:MAINWP_APP_PASSWORD = 'xxxx xxxx xxxx xxxx xxxx xxxx' ``` -For long-term storage, use the OS keychain (the default when you run `mainwpctl login`) or a restricted-permission `.env` file rather than pasting credentials into shell profile files. +For long-term storage, use the OS keychain (the default when you run `mainwpcontrol login`) or a restricted-permission `.env` file rather than pasting credentials into shell profile files. ### What is an Application Password? -WordPress Application Passwords let external tools like `mainwpctl` access your site without using your main login password. They look like groups of four characters separated by spaces (e.g., `abcd efgh ijkl mnop qrst uvwx`). +WordPress Application Passwords let external tools like `mainwpcontrol` access your site without using your main login password. They look like groups of four characters separated by spaces (e.g., `abcd efgh ijkl mnop qrst uvwx`). -**To create one:** Log into WordPress admin > Users > Your Profile > scroll to **Application Passwords** > enter a name like "mainwpctl" > click **Add New Application Password** > copy the generated password. +**To create one:** Log into WordPress admin > Users > Your Profile > scroll to **Application Passwords** > enter a name like "mainwpcontrol" > click **Add New Application Password** > copy the generated password. ### Reading command output When you run a command, the output appears in your terminal. A few things to know: -- **`--json`** tells `mainwpctl` to output structured JSON (useful for scripting and piping to other tools) +- **`--json`** tells `mainwpcontrol` to output structured JSON (useful for scripting and piping to other tools) - **Exit codes** indicate success (`0`) or failure (`1` through `5`). You won't see them directly, but scripts and CI use them to decide what happens next. Run `echo $?` (macOS/Linux) or `echo $LASTEXITCODE` (PowerShell) after a command to check. @@ -117,12 +117,12 @@ We recommend a two-step pattern for destructive operations: preview first, then ```bash # Step 1: Preview what will be deleted (nothing changes) -mainwpctl abilities run delete-site-v1 \ +mainwpcontrol abilities run delete-site-v1 \ --input '{"site_id_or_domain": "mysite.com"}' \ --dry-run --json # Step 2: Execute after reviewing the preview -mainwpctl abilities run delete-site-v1 \ +mainwpcontrol abilities run delete-site-v1 \ --input '{"site_id_or_domain": "mysite.com"}' \ --confirm --force --json ``` @@ -147,16 +147,16 @@ The MainWP Abilities API provides all available operations: ```bash # List all abilities -mainwpctl abilities list +mainwpcontrol abilities list # Get ability details (input schema, annotations) -mainwpctl abilities info +mainwpcontrol abilities info # Execute an ability -mainwpctl abilities run [--input JSON] [--input-file path] [--json] +mainwpcontrol abilities run [--input JSON] [--input-file path] [--json] # Execute and wait for batch completion -mainwpctl abilities run --wait [--wait-timeout 300] --json +mainwpcontrol abilities run --wait [--wait-timeout 300] --json ``` ### Batch Jobs @@ -165,49 +165,49 @@ Monitor long-running batch operations: ```bash # Watch a batch job -mainwpctl jobs watch +mainwpcontrol jobs watch # With timeout -mainwpctl jobs watch --timeout 120 +mainwpcontrol jobs watch --timeout 120 ``` ### Diagnostics ```bash # Check configuration and connectivity -mainwpctl doctor +mainwpcontrol doctor # Verbose output with details -mainwpctl doctor -v +mainwpcontrol doctor -v # JSON output for scripting -mainwpctl doctor --json +mainwpcontrol doctor --json ``` ### Profile Management ```bash # List all profiles -mainwpctl profile list +mainwpcontrol profile list # Switch active profile -mainwpctl profile use +mainwpcontrol profile use ``` ### Authentication ```bash # Interactive login (stores credentials in OS keychain) -mainwpctl login +mainwpcontrol login # Non-interactive login for CI/containers (password from env var) export MAINWP_APP_PASSWORD='your-application-password' -mainwpctl login --url https://dashboard.example.com --username admin +mainwpcontrol login --url https://dashboard.example.com --username admin ``` -To create an Application Password: log into WordPress admin > Users > Your Profile > Application Passwords > add a new password named "mainwpctl". +To create an Application Password: log into WordPress admin > Users > Your Profile > Application Passwords > add a new password named "mainwpcontrol". -When the OS keychain is unavailable, `mainwpctl` does not persist plaintext credentials. Keep `MAINWP_APP_PASSWORD` set for each non-interactive run on CI, cron hosts, and headless servers. +When the OS keychain is unavailable, `mainwpcontrol` does not persist plaintext credentials. Keep `MAINWP_APP_PASSWORD` set for each non-interactive run on CI, cron hosts, and headless servers. ### Chat Mode @@ -215,10 +215,10 @@ Optional interactive mode for exploring abilities before scripting them. Require ```bash # Interactive chat -mainwpctl chat +mainwpcontrol chat # Single message (works in scripts) -mainwpctl chat "list all sites with pending updates" +mainwpcontrol chat "list all sites with pending updates" ``` Chat requires one of these environment variables: @@ -228,7 +228,7 @@ Chat requires one of these environment variables: - `OPENROUTER_API_KEY` (OpenRouter) - `LOCAL_LLM_API_KEY` (Local endpoint, with optional `LOCAL_LLM_URL`) -In non-TTY environments (pipes, CI), `mainwpctl chat` without a message exits with guidance. Use `mainwpctl chat "message"` for single-message mode in scripts. +In non-TTY environments (pipes, CI), `mainwpcontrol chat` without a message exits with guidance. Use `mainwpcontrol chat "message"` for single-message mode in scripts. --- @@ -304,7 +304,7 @@ In CI/scripted workflows, you can pass `--confirm --force` directly if you've al ## Configuration File -Settings in `~/.config/mainwpctl/settings.json`: +Settings in `~/.config/mainwpcontrol/settings.json`: ```json { @@ -326,7 +326,7 @@ Settings in `~/.config/mainwpctl/settings.json`: | `skipSSLVerification` | boolean | Advanced fallback: disable TLS verification when the active profile does not set its own SSL preference | | `allowInsecureHttp` | boolean | Advanced fallback: allow `http://` Dashboard URLs without setting `MAINWP_ALLOW_HTTP=1` | -`skipSSLVerification` and `allowInsecureHttp` are insecure overrides. Prefer storing TLS behavior on the profile with `mainwpctl login --skip-ssl-verify`, and keep HTTPS as the default transport. +`skipSSLVerification` and `allowInsecureHttp` are insecure overrides. Prefer storing TLS behavior on the profile with `mainwpcontrol login --skip-ssl-verify`, and keep HTTPS as the default transport. --- @@ -334,10 +334,10 @@ Settings in `~/.config/mainwpctl/settings.json`: ```bash # Bash -source /path/to/mainwpctl/scripts/completions/mainwpctl.bash +source /path/to/mainwp-control/scripts/completions/mainwpcontrol.bash # Zsh -source /path/to/mainwpctl/scripts/completions/mainwpctl.zsh +source /path/to/mainwp-control/scripts/completions/mainwpcontrol.zsh ``` ## Requirements @@ -358,7 +358,7 @@ Keytar requires native C++ compilation on some platforms. If it fails: 1. **Use environment variable auth instead** (bypasses keytar entirely): ```bash export MAINWP_APP_PASSWORD='your-application-password' - mainwpctl login --url https://dashboard.example.com --username admin + mainwpcontrol login --url https://dashboard.example.com --username admin ``` 2. **Or skip keytar explicitly** by setting `MAINWPCTL_NO_KEYTAR=1` before running commands. @@ -389,15 +389,15 @@ On Windows, the npm global directory is usually already in PATH after installing
"connection refused" or network errors -If `mainwpctl login` or commands fail with connection errors: +If `mainwpcontrol login` or commands fail with connection errors: 1. **Check the Dashboard URL.** Make sure it's the full URL with `https://` (e.g., `https://dashboard.example.com`). Don't include a trailing slash. -2. **Verify HTTPS.** `mainwpctl` requires HTTPS by default. If your Dashboard uses HTTP (not recommended), set `MAINWP_ALLOW_HTTP=1`. +2. **Verify HTTPS.** `mainwpcontrol` requires HTTPS by default. If your Dashboard uses HTTP (not recommended), set `MAINWP_ALLOW_HTTP=1`. 3. **Check firewall/network.** Make sure your machine can reach the Dashboard: ```bash curl -I https://dashboard.example.com ``` -4. **SSL certificate issues.** If using a self-signed certificate, you can use `mainwpctl login --skip-ssl-verify` (not recommended for production). +4. **SSL certificate issues.** If using a self-signed certificate, you can use `mainwpcontrol login --skip-ssl-verify` (not recommended for production).
diff --git a/docs/workflows/daily-health-check.md b/docs/workflows/daily-health-check.md index 9ee28ed..758d01e 100644 --- a/docs/workflows/daily-health-check.md +++ b/docs/workflows/daily-health-check.md @@ -35,7 +35,7 @@ Application Passwords are a WordPress feature that lets external tools (like Mai 1. Log in to your WordPress Dashboard site as an administrator. 2. Navigate to **Users > Your Profile** (or click your name in the top-right corner and select "Edit Profile"). 3. Scroll down to the **Application Passwords** section near the bottom of the page. -4. In the **"New Application Password Name"** field, type a name to identify this credential, for example `mainwpctl`. +4. In the **"New Application Password Name"** field, type a name to identify this credential, for example `mainwpcontrol`. 5. Click **"Add New Application Password"**. 6. WordPress will display a generated password. It looks something like this: @@ -56,7 +56,7 @@ MainWP Control is a command-line tool distributed as an npm package. npm is the ### Option A: Install globally (recommended) -A global install makes `mainwpctl` available as a command anywhere on your system: +A global install makes `mainwpcontrol` available as a command anywhere on your system: ```bash npm install -g @mainwp/control @@ -67,7 +67,7 @@ npm install -g @mainwp/control If you cannot or prefer not to install packages globally, you can use `npx` to run MainWP Control on demand. npx downloads and runs the package temporarily: ```bash -npx mainwpctl +npx --package=@mainwp/control mainwpcontrol ``` ### Option C: Install in a project directory @@ -78,23 +78,23 @@ If you are integrating MainWP Control into an existing project: npm install @mainwp/control ``` -Then run it with `npx mainwpctl` from that project directory. +Then run it with `npx mainwpcontrol` from that project directory. ### Verify the installation Run the following command to confirm MainWP Control is installed and working: ```bash -mainwpctl --version +mainwpcontrol --version ``` Expected output: ``` -mainwpctl/x.y.z darwin-arm64 node-vNN.NN.N +mainwpcontrol/x.y.z darwin-arm64 node-vNN.NN.N ``` -You should see `mainwpctl/` followed by version information. The exact values depend on your system and Node.js version. +You should see `mainwpcontrol/` followed by version information. The exact values depend on your system and Node.js version. --- @@ -105,7 +105,7 @@ MainWP Control needs to know which MainWP Dashboard to connect to and how to aut Run: ```bash -mainwpctl login +mainwpcontrol login ``` You will be prompted for three pieces of information: @@ -121,7 +121,7 @@ After entering these, MainWP Control stores your credentials in your system's ke Run the built-in diagnostic command: ```bash -mainwpctl doctor +mainwpcontrol doctor ``` Expected output: @@ -150,7 +150,7 @@ Expected output: ✓ System is ready ``` -The key line is `✓ System is ready`. If any check fails, run `mainwpctl doctor -v` for details. If authentication fails, double-check your URL, username, and Application Password. +The key line is `✓ System is ready`. If any check fails, run `mainwpcontrol doctor -v` for details. If authentication fails, double-check your URL, username, and Application Password. --- @@ -182,7 +182,7 @@ Before writing the script, confirm the webhook works by sending a test message. ```bash curl -X POST -H 'Content-Type: application/json' \ - -d '{"text":"Test from mainwpctl setup"}' \ + -d '{"text":"Test from mainwpcontrol setup"}' \ 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL' ``` @@ -194,7 +194,7 @@ Expected result in your terminal: ok ``` -Expected result in Slack: A message reading "Test from mainwpctl setup" appears in the channel you selected. +Expected result in Slack: A message reading "Test from mainwpcontrol setup" appears in the channel you selected. If you see an error or the message does not appear, double-check that you copied the full webhook URL and that the Slack app is still active. @@ -220,7 +220,7 @@ Enter the following content: #!/bin/bash # mainwp-health-check.sh - Check MainWP site connectivity -RESULT=$(mainwpctl abilities run list-sites-v1 --json 2>/dev/null) +RESULT=$(mainwpcontrol abilities run list-sites-v1 --json 2>/dev/null) echo "$RESULT" ``` @@ -228,7 +228,7 @@ Here is what each line does: - `#!/bin/bash`: This is called a **shebang**. It tells your operating system which program to use to run this script. `/bin/bash` is the Bash shell, which is available on macOS and virtually all Linux systems. - `# mainwp-health-check.sh ...`: Lines starting with `#` are **comments**. They are ignored when the script runs and exist only to help humans understand the code. -- `RESULT=$(mainwpctl abilities run list-sites-v1 --json 2>/dev/null)`: This runs the MainWP Control command that lists all sites, captures its output into a **variable** called `RESULT`. The `--json` flag tells MainWP Control to output structured JSON data instead of human-readable text. The `2>/dev/null` part hides any warning messages so only the JSON output is captured. +- `RESULT=$(mainwpcontrol abilities run list-sites-v1 --json 2>/dev/null)`: This runs the MainWP Control command that lists all sites, captures its output into a **variable** called `RESULT`. The `--json` flag tells MainWP Control to output structured JSON data instead of human-readable text. The `2>/dev/null` part hides any warning messages so only the JSON output is captured. - `echo "$RESULT"`: This prints the captured output to the terminal so you can see it. Save the file (in nano: press `Ctrl+O`, then `Enter`, then `Ctrl+X` to exit). @@ -275,13 +275,13 @@ The exact sites and details will match your MainWP Dashboard. The important thin An **exit code** is a number that every command returns when it finishes. An exit code of `0` means success. Any other number means something went wrong. The variable `$?` contains the exit code of the most recently run command. -Update your script to check whether the mainwpctl command succeeded: +Update your script to check whether the mainwpcontrol command succeeded: ```bash #!/bin/bash # mainwp-health-check.sh - Check MainWP site connectivity -RESULT=$(mainwpctl abilities run list-sites-v1 --json 2>/dev/null) +RESULT=$(mainwpcontrol abilities run list-sites-v1 --json 2>/dev/null) EXIT=$? if [ $EXIT -ne 0 ]; then @@ -294,7 +294,7 @@ echo "Command succeeded. Site data retrieved." New lines explained: -- `EXIT=$?`: Captures the exit code of the mainwpctl command into a variable called `EXIT`. +- `EXIT=$?`: Captures the exit code of the mainwpcontrol command into a variable called `EXIT`. - `if [ $EXIT -ne 0 ]; then`: This is a **conditional**. `-ne` means "not equal to". So this reads: "if the exit code is not equal to zero, then..." - `echo "Health check command failed with exit code $EXIT"`: Prints an error message that includes the actual exit code. - `exit 1`: Stops the script immediately and reports failure (exit code 1). @@ -348,7 +348,7 @@ Now update the script to count disconnected sites: #!/bin/bash # mainwp-health-check.sh - Check MainWP site connectivity -RESULT=$(mainwpctl abilities run list-sites-v1 --json 2>/dev/null) +RESULT=$(mainwpcontrol abilities run list-sites-v1 --json 2>/dev/null) EXIT=$? if [ $EXIT -ne 0 ]; then @@ -399,7 +399,7 @@ Now we bring it all together. When the health check fails or finds disconnected SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" # Run the health check -RESULT=$(mainwpctl abilities run list-sites-v1 --json 2>/dev/null) +RESULT=$(mainwpcontrol abilities run list-sites-v1 --json 2>/dev/null) EXIT=$? # Alert if the command itself failed @@ -531,7 +531,7 @@ For example, if the script is in your home directory, the line might be: 0 7 * * * /Users/yourname/mainwp-health-check.sh ``` -**Note on PATH:** Cron runs in a minimal environment. It does not load your shell profile, so commands like `mainwpctl` or `jq` may not be found by their short names. If you encounter issues, add a `PATH` line at the top of your crontab: +**Note on PATH:** Cron runs in a minimal environment. It does not load your shell profile, so commands like `mainwpcontrol` or `jq` may not be found by their short names. If you encounter issues, add a `PATH` line at the top of your crontab: ``` PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin @@ -618,7 +618,7 @@ jq is not installed on your system. Install it: - On Linux: `grep CRON /var/log/syslog` - On macOS: `log show --predicate 'process == "cron"' --last 1h` -- **Make sure you used full paths** for both the script and any commands inside it (mainwpctl, jq, curl). Cron does not load your shell profile, so it may not find programs by their short names. Adding a `PATH` line to the top of your crontab (as shown in Step 8) usually resolves this. +- **Make sure you used full paths** for both the script and any commands inside it (mainwpcontrol, jq, curl). Cron does not load your shell profile, so it may not find programs by their short names. Adding a `PATH` line to the top of your crontab (as shown in Step 8) usually resolves this. - **On macOS**, you may need to grant Terminal (or your terminal app) **Full Disk Access** in **System Settings > Privacy & Security > Full Disk Access**. Without this, cron may be silently blocked from running scripts. @@ -633,10 +633,10 @@ chmod +x mainwp-health-check.sh If MainWP Control itself fails with a permission error, check that your authentication is still valid: ```bash -mainwpctl doctor -v +mainwpcontrol doctor -v ``` -If the doctor command reports authentication issues, run `mainwpctl login` again. +If the doctor command reports authentication issues, run `mainwpcontrol login` again. ### Authentication errors in cron diff --git a/docs/workflows/input-from-file.md b/docs/workflows/input-from-file.md index 49065a2..1c2ffd0 100644 --- a/docs/workflows/input-from-file.md +++ b/docs/workflows/input-from-file.md @@ -1,6 +1,6 @@ # Input from File -> Pass complex parameters to mainwpctl using JSON files, stdin pipes, or heredocs instead of typing everything on the command line. +> Pass complex parameters to mainwpcontrol using JSON files, stdin pipes, or heredocs instead of typing everything on the command line. MainWP Control is a command-line tool for managing your MainWP Dashboard and all the WordPress sites connected to it. Some operations need structured data as input: site IDs, lists of plugins, or nested configuration objects. This guide shows you three ways to pass that structured data without wrestling with long, error-prone command-line strings. @@ -20,7 +20,7 @@ MainWP Control is a command-line tool for managing your MainWP Dashboard and all Some MainWP Control abilities need more than a flag. For example, updating specific plugins on a specific site requires a JSON object with a site ID and a list of plugin slugs. Typing this as an `--input` flag works for simple cases: ```bash -mainwpctl abilities run get-site-v1 --input '{"site_id_or_domain": 5}' --json +mainwpcontrol abilities run get-site-v1 --input '{"site_id_or_domain": 5}' --json ``` But when parameters get complex (nested objects, arrays, multiple fields), inline JSON becomes hard to read and easy to get wrong. A misplaced quote or missing comma can cause confusing errors. @@ -60,7 +60,7 @@ MainWP Control authenticates with your MainWP Dashboard using a WordPress Applic 1. Log in to your WordPress Dashboard site as an administrator. 2. Go to **Users > Your Profile** (click your username in the top-right, then "Edit Profile", or navigate to `/wp-admin/profile.php`). 3. Scroll down to the **Application Passwords** section near the bottom of the page. -4. In the "New Application Password Name" field, type a name you will recognize later, for example: `mainwpctl` +4. In the "New Application Password Name" field, type a name you will recognize later, for example: `mainwpcontrol` 5. Click **Add New Application Password**. 6. WordPress will display a password that looks something like this: @@ -71,7 +71,7 @@ MainWP Control authenticates with your MainWP Dashboard using a WordPress Applic 7. **Copy this password immediately.** WordPress will not show it again. If you lose it, you will need to create a new one. 8. Store it somewhere secure (a password manager is ideal). -The spaces in the password are optional. mainwpctl accepts the password with or without them. +The spaces in the password are optional. mainwpcontrol accepts the password with or without them. --- @@ -92,24 +92,24 @@ npm install -g @mainwp/control If you prefer not to install globally, you can run MainWP Control on demand using `npx`: ```bash -npx mainwpctl --version +npx --package=@mainwp/control mainwpcontrol --version ``` -`npx` downloads and runs the package temporarily. Every example in this guide uses `mainwpctl` directly. If you chose Option B, replace `mainwpctl` with `npx mainwpctl` in every command. +`npx` downloads and runs the package temporarily. Every example in this guide uses `mainwpcontrol` directly. If you chose Option B, replace `mainwpcontrol` with `npx --package=@mainwp/control mainwpcontrol` in every command. ### Verify the installation ```bash -mainwpctl --version +mainwpcontrol --version ``` Expected output: ``` -mainwpctl/x.y.z +mainwpcontrol/x.y.z ``` -You should see `mainwpctl/` followed by a version number. The exact values depend on your system. +You should see `mainwpcontrol/` followed by a version number. The exact values depend on your system. --- @@ -118,7 +118,7 @@ You should see `mainwpctl/` followed by a version number. The exact values depen Run the interactive login command: ```bash -mainwpctl login +mainwpcontrol login ``` MainWP Control will prompt you for three pieces of information: @@ -132,7 +132,7 @@ Enter each value when prompted. MainWP Control will test the connection and stor ### Verify authentication ```bash -mainwpctl doctor +mainwpcontrol doctor ``` Expected output: @@ -203,13 +203,13 @@ Save the file in a directory you can easily navigate to in your terminal. Here is what each part means: - `{` and `}`: the outer curly braces define a JSON object (a collection of key-value pairs) -- `"site_id_or_domain"`: the key, which tells mainwpctl which parameter you are setting +- `"site_id_or_domain"`: the key, which tells mainwpcontrol which parameter you are setting - `:` separates the key from the value - `5`: the value (a number representing the site ID in your MainWP Dashboard) This is the simplest possible parameter file. It passes a single site ID to an ability. -**How do you find your site ID?** Run `mainwpctl abilities run list-sites-v1 --json` to see all your connected sites. Each site in the output will have an `id` field. Replace `5` with your actual site ID. +**How do you find your site ID?** Run `mainwpcontrol abilities run list-sites-v1 --json` to see all your connected sites. Each site in the output will have an `id` field. Replace `5` with your actual site ID. ### A more complex example @@ -222,7 +222,7 @@ For updating specific plugins on a site, you might need: } ``` -This adds a second parameter called `plugins`. The value is an array (a list) containing two plugin slugs. A plugin slug is the short name used in the plugin's directory. You can find it by running `mainwpctl abilities run get-site-plugins-v1 --input '{"site_id_or_domain": 5}' --json` and looking at the `slug` field for each plugin. +This adds a second parameter called `plugins`. The value is an array (a list) containing two plugin slugs. A plugin slug is the short name used in the plugin's directory. You can find it by running `mainwpcontrol abilities run get-site-plugins-v1 --input '{"site_id_or_domain": 5}' --json` and looking at the `slug` field for each plugin. Notice the comma after `5` on the first line. Commas separate items within an object. There is no comma after the last item (`"plugins"` line). @@ -233,12 +233,12 @@ Notice the comma after `5` on the first line. Commas separate items within an ob Now that you have a `params.json` file, use it with the `--input-file` flag: ```bash -mainwpctl abilities run get-site-v1 --input-file params.json --json +mainwpcontrol abilities run get-site-v1 --input-file params.json --json ``` Here is what each part of this command does: -- `mainwpctl abilities run`: tells MainWP Control to execute an ability +- `mainwpcontrol abilities run`: tells MainWP Control to execute an ability - `get-site-v1`: the name of the ability (fetches details about a specific site) - `--input-file params.json`: read the parameters from your `params.json` file instead of the command line - `--json`: output the result as structured JSON (easier to read and use in scripts) @@ -246,7 +246,7 @@ Here is what each part of this command does: The file path (`params.json`) is relative to the directory where you run the command. If you are in `/home/user/projects` and the file is at `/home/user/projects/params.json`, then `params.json` works. You can also use an absolute path: ```bash -mainwpctl abilities run get-site-v1 --input-file /home/user/projects/params.json --json +mainwpcontrol abilities run get-site-v1 --input-file /home/user/projects/params.json --json ``` Expected output (your values will differ): @@ -277,7 +277,7 @@ Expected output (your values will differ): Some abilities make changes: updating plugins, deleting themes, modifying site settings. These are called destructive operations. For safety, MainWP Control requires you to explicitly confirm them: ```bash -mainwpctl abilities run update-site-plugins-v1 --input-file params.json --confirm --force +mainwpcontrol abilities run update-site-plugins-v1 --input-file params.json --confirm --force ``` - `--confirm`: tells MainWP Control you have reviewed the action and want to proceed @@ -298,14 +298,14 @@ Think of it like a conveyor belt: the command on the left produces data, the pip ### Basic pipe ```bash -echo '{"site_id_or_domain": 5}' | mainwpctl abilities run get-site-v1 --input - --json +echo '{"site_id_or_domain": 5}' | mainwpcontrol abilities run get-site-v1 --input - --json ``` Here is what happens: 1. `echo '{"site_id_or_domain": 5}'`: the `echo` command outputs the JSON string to the terminal 2. `|`: the pipe takes that output and sends it as input to the next command -3. `mainwpctl abilities run get-site-v1 --input - --json`: mainwpctl runs the ability, and `--input -` tells it to read parameters from stdin (the `-` character means "read from the pipe instead of from a flag value") +3. `mainwpcontrol abilities run get-site-v1 --input - --json`: mainwpcontrol runs the ability, and `--input -` tells it to read parameters from stdin (the `-` character means "read from the pipe instead of from a flag value") Expected output: @@ -328,20 +328,20 @@ Expected output: ### Pipe from a file -You can also pipe the contents of a file into mainwpctl: +You can also pipe the contents of a file into mainwpcontrol: ```bash -cat params.json | mainwpctl abilities run get-site-v1 --input - --json +cat params.json | mainwpcontrol abilities run get-site-v1 --input - --json ``` -`cat` is a command that reads a file and outputs its contents. The pipe then sends those contents to mainwpctl. This is equivalent to `--input-file params.json` but is useful when you want to chain multiple commands together or add processing steps between reading the file and sending it to MainWP Control. +`cat` is a command that reads a file and outputs its contents. The pipe then sends those contents to mainwpcontrol. This is equivalent to `--input-file params.json` but is useful when you want to chain multiple commands together or add processing steps between reading the file and sending it to MainWP Control. ### Pipe from another command You can generate JSON dynamically and pipe it directly: ```bash -printf '{"site_id_or_domain": %d}' 5 | mainwpctl abilities run get-site-v1 --input - --json +printf '{"site_id_or_domain": %d}' 5 | mainwpcontrol abilities run get-site-v1 --input - --json ``` `printf` is like `echo` but gives you more control over formatting. The `%d` is a placeholder that gets replaced with the number `5`. This is useful in scripts where the site ID comes from a variable or another command's output. @@ -361,7 +361,7 @@ The syntax `<<'EOF'` means: "everything from here until you see `EOF` on its own ### Basic heredoc ```bash -mainwpctl abilities run get-site-v1 --input - --json <<'EOF' +mainwpcontrol abilities run get-site-v1 --input - --json <<'EOF' { "site_id_or_domain": 5 } @@ -370,7 +370,7 @@ EOF Here is what each part does: -- `mainwpctl abilities run get-site-v1 --input - --json`: runs the ability, reading parameters from stdin +- `mainwpcontrol abilities run get-site-v1 --input - --json`: runs the ability, reading parameters from stdin - `<<'EOF'`: starts the heredoc. The single quotes around `EOF` are important (explained below) - The lines between `<<'EOF'` and `EOF` are the JSON content sent as stdin - `EOF` on its own line (no spaces before it, nothing after it): ends the heredoc @@ -397,7 +397,7 @@ Expected output: ### A more complex heredoc ```bash -mainwpctl abilities run update-site-plugins-v1 --input - --confirm --force <<'EOF' +mainwpcontrol abilities run update-site-plugins-v1 --input - --confirm --force <<'EOF' { "site_id_or_domain": 5, "plugins": ["akismet", "wordfence"] @@ -418,13 +418,13 @@ For JSON, **always use `<<'EOF'` (with single quotes)**. Here is why: ```bash # With quotes - CORRECT for JSON -mainwpctl abilities run get-site-v1 --input - --json <<'EOF' +mainwpcontrol abilities run get-site-v1 --input - --json <<'EOF' {"site_id_or_domain": 5} EOF -# mainwpctl receives: {"site_id_or_domain": 5} +# mainwpcontrol receives: {"site_id_or_domain": 5} # Without quotes - DANGEROUS for JSON -mainwpctl abilities run get-site-v1 --input - --json < test-params.json -mainwpctl abilities run get-site-v1 --input-file test-params.json --json +mainwpcontrol abilities run get-site-v1 --input-file test-params.json --json # Method 3: heredoc -mainwpctl abilities run get-site-v1 --input - --json <<'EOF' +mainwpcontrol abilities run get-site-v1 --input - --json <<'EOF' {"site_id_or_domain": 5} EOF ``` @@ -518,7 +518,7 @@ Remove the comma after the last key-value pair in an object or the last element - **Use the full (absolute) path** to avoid ambiguity: ```bash - mainwpctl abilities run get-site-v1 --input-file /home/user/params.json --json + mainwpcontrol abilities run get-site-v1 --input-file /home/user/params.json --json ``` - **Or make sure you are in the right directory.** Run `pwd` to see your current directory, and `ls` to list files in it. The file must be in that directory (or you must specify the path to it). - **Filenames are case-sensitive on Linux and macOS.** `Params.json` is not the same as `params.json`. @@ -527,7 +527,7 @@ Remove the comma after the last key-value pair in an object or the last element - **Make sure the pipe is correct.** The JSON-producing command must come before the `|`: ```bash - echo '{"site_id_or_domain": 5}' | mainwpctl abilities run get-site-v1 --input - --json + echo '{"site_id_or_domain": 5}' | mainwpcontrol abilities run get-site-v1 --input - --json ``` - **If using a heredoc**, make sure the closing `EOF` is on its own line with no leading spaces or tabs. Even one space before `EOF` will cause the shell to miss it: ``` @@ -546,7 +546,7 @@ Remove the comma after the last key-value pair in an object or the last element Use the `abilities info` command to see the expected input schema for any ability: ```bash -mainwpctl abilities info get-site-v1 +mainwpcontrol abilities info get-site-v1 ``` This shows you which fields are required, which are optional, and what types they expect (string, number, array, etc.). Use this output to build your JSON parameter file. @@ -556,7 +556,7 @@ This shows you which fields are required, which are optional, and what types the Try running your command with `--debug` for more detailed error output: ```bash -mainwpctl abilities run get-site-v1 --input-file params.json --json --debug +mainwpcontrol abilities run get-site-v1 --input-file params.json --json --debug ``` The debug output will show you what MainWP Control received as input and where it failed. diff --git a/docs/workflows/monitoring-integration.md b/docs/workflows/monitoring-integration.md index f0e4d46..7c27f09 100644 --- a/docs/workflows/monitoring-integration.md +++ b/docs/workflows/monitoring-integration.md @@ -36,7 +36,7 @@ Application Passwords are a WordPress feature that lets external tools (like Mai 1. Log in to your WordPress Dashboard site as an administrator. 2. Navigate to **Users > Your Profile** (or click your name in the top-right corner and select "Edit Profile"). 3. Scroll down to the **Application Passwords** section near the bottom of the page. -4. In the **"New Application Password Name"** field, type a name to identify this credential, for example `mainwpctl`. +4. In the **"New Application Password Name"** field, type a name to identify this credential, for example `mainwpcontrol`. 5. Click **"Add New Application Password"**. 6. WordPress will display a generated password. It looks something like this: @@ -57,7 +57,7 @@ MainWP Control is a command-line tool distributed as an npm package. npm is the ### Option A: Install globally (recommended) -A global install makes `mainwpctl` available as a command anywhere on your system: +A global install makes `mainwpcontrol` available as a command anywhere on your system: ```bash npm install -g @mainwp/control @@ -68,7 +68,7 @@ npm install -g @mainwp/control If you cannot or prefer not to install packages globally, you can use `npx` to run MainWP Control on demand. npx downloads and runs the package temporarily: ```bash -npx mainwpctl +npx --package=@mainwp/control mainwpcontrol ``` ### Verify the installation @@ -76,16 +76,16 @@ npx mainwpctl Run the following command to confirm MainWP Control is installed and working: ```bash -mainwpctl --version +mainwpcontrol --version ``` Expected output: ``` -mainwpctl/x.y.z darwin-arm64 node-vNN.NN.N +mainwpcontrol/x.y.z darwin-arm64 node-vNN.NN.N ``` -You should see `mainwpctl/` followed by a version number. The exact values depend on your system. +You should see `mainwpcontrol/` followed by a version number. The exact values depend on your system. --- @@ -96,7 +96,7 @@ MainWP Control needs to know which MainWP Dashboard to connect to and how to aut Run: ```bash -mainwpctl login +mainwpcontrol login ``` You will be prompted for three pieces of information: @@ -112,7 +112,7 @@ After entering these, MainWP Control stores your credentials in your system's ke Run the built-in diagnostic command: ```bash -mainwpctl doctor +mainwpcontrol doctor ``` Expected output: @@ -141,7 +141,7 @@ Expected output: ✓ System is ready ``` -The key line is `✓ System is ready`. If any check fails, run `mainwpctl doctor -v` for details. If authentication fails, double-check your URL, username, and Application Password. +The key line is `✓ System is ready`. If any check fails, run `mainwpcontrol doctor -v` for details. If authentication fails, double-check your URL, username, and Application Password. --- @@ -178,7 +178,7 @@ The version number may vary. Any version will work for our purposes. Start by listing all sites connected to your MainWP Dashboard: ```bash -mainwpctl abilities run list-sites-v1 --json +mainwpcontrol abilities run list-sites-v1 --json ``` Expected output (abbreviated): @@ -213,7 +213,7 @@ Expected output (abbreviated): The exact sites will match your Dashboard. Now extract the count using jq: ```bash -mainwpctl abilities run list-sites-v1 --json | jq '.data.data.items | length' +mainwpcontrol abilities run list-sites-v1 --json | jq '.data.data.items | length' ``` Here is what the jq expression means: @@ -234,7 +234,7 @@ The number will match how many sites are connected to your Dashboard. ### Pending update count ```bash -mainwpctl abilities run list-updates-v1 --json | jq '.data.data.total // 0' +mainwpcontrol abilities run list-updates-v1 --json | jq '.data.data.total // 0' ``` The jq expression `.data.data.total // 0` means: "get the `total` field from the inner `data` object, or use `0` if it does not exist." The `//` operator is jq's alternative operator, providing a fallback value when a field is missing or null. @@ -250,7 +250,7 @@ This is the total number of pending updates (plugins, themes, and core) across a ### Disconnected site count ```bash -mainwpctl abilities run list-sites-v1 --json | jq '[.data.data.items[] | select(.status != "connected")] | length' +mainwpcontrol abilities run list-sites-v1 --json | jq '[.data.data.items[] | select(.status != "connected")] | length' ``` This jq expression is more involved, so here is what each part does: @@ -290,7 +290,7 @@ StatsD is a protocol for sending metrics to monitoring systems. It is text-based Start with getting the count and printing it: ```bash -SITE_COUNT=$(mainwpctl abilities run list-sites-v1 --json | jq '.data.data.items | length') +SITE_COUNT=$(mainwpcontrol abilities run list-sites-v1 --json | jq '.data.data.items | length') echo "Site count: $SITE_COUNT" ``` @@ -305,7 +305,7 @@ Site count: 12 Next, format it as a StatsD metric: ```bash -SITE_COUNT=$(mainwpctl abilities run list-sites-v1 --json | jq '.data.data.items | length') +SITE_COUNT=$(mainwpcontrol abilities run list-sites-v1 --json | jq '.data.data.items | length') echo "mainwp.sites.total:${SITE_COUNT}|g" ``` @@ -324,7 +324,7 @@ Here is what this string means: Finally, send it to StatsD: ```bash -mainwpctl abilities run list-sites-v1 --json | \ +mainwpcontrol abilities run list-sites-v1 --json | \ jq '.data.data.items | length' | \ xargs -I {} echo "mainwp.sites.total:{}|g" | \ nc -u -w1 localhost 8125 @@ -332,7 +332,7 @@ mainwpctl abilities run list-sites-v1 --json | \ Each line in this pipeline does one thing: -1. `mainwpctl abilities run list-sites-v1 --json`: Fetches the site data as JSON from your MainWP Dashboard. +1. `mainwpcontrol abilities run list-sites-v1 --json`: Fetches the site data as JSON from your MainWP Dashboard. 2. `jq '.data.data.items | length'`: Extracts the site count from the JSON. 3. `xargs -I {} echo "mainwp.sites.total:{}|g"`: Formats the count as a StatsD metric string. `xargs` takes the input (the count) and passes it to the `echo` command. `-I {}` means "replace `{}` with the input value." 4. `nc -u -w1 localhost 8125`: Sends the formatted string via UDP (`-u`) to localhost port 8125 with a 1-second timeout (`-w1`). @@ -348,7 +348,7 @@ There is no output from this command if it succeeds. The metric is sent silently The same pattern works for any metric. Here is the one-liner for pending updates: ```bash -mainwpctl abilities run list-updates-v1 --json | \ +mainwpcontrol abilities run list-updates-v1 --json | \ jq '.data.data.total // 0' | \ xargs -I {} echo "mainwp.updates.pending:{}|g" | \ nc -u -w1 localhost 8125 @@ -356,7 +356,7 @@ mainwpctl abilities run list-updates-v1 --json | \ The only differences from the previous step: -- The mainwpctl command fetches updates instead of sites (`list-updates-v1` instead of `list-sites-v1`). +- The mainwpcontrol command fetches updates instead of sites (`list-updates-v1` instead of `list-sites-v1`). - The jq expression extracts `.data.data.total` instead of the sites array length. - The metric name is `mainwp.updates.pending` instead of `mainwp.sites.total`. @@ -369,7 +369,7 @@ What happens when MainWP Control fails, for example if your Dashboard is unreach Error handling fixes this. Here is a version that detects failure and sends a different metric to alert you: ```bash -RESULT=$(mainwpctl abilities run list-sites-v1 --json 2>/dev/null) +RESULT=$(mainwpcontrol abilities run list-sites-v1 --json 2>/dev/null) EXIT=$? if [ $EXIT -ne 0 ]; then @@ -429,7 +429,7 @@ Add the following below the `send_metric` function: ```bash # Site count and disconnected count -SITES=$(mainwpctl abilities run list-sites-v1 --json 2>/dev/null) +SITES=$(mainwpcontrol abilities run list-sites-v1 --json 2>/dev/null) if [ $? -eq 0 ]; then TOTAL=$(echo "$SITES" | jq '.data.data.items | length') DISCONNECTED=$(echo "$SITES" | jq '[.data.data.items[] | select(.status != "connected")] | length') @@ -440,7 +440,7 @@ else fi ``` -Notice that we call `mainwpctl abilities run list-sites-v1` only once and extract two metrics (total count and disconnected count) from the same response. This is efficient: each API call takes a few seconds, so reusing the result saves time. +Notice that we call `mainwpcontrol abilities run list-sites-v1` only once and extract two metrics (total count and disconnected count) from the same response. This is efficient: each API call takes a few seconds, so reusing the result saves time. The `$? -eq 0` check means "the exit code equals zero," i.e., the command succeeded. `-eq` means "equal to." @@ -450,7 +450,7 @@ Add this below the site metrics block: ```bash # Pending updates -UPDATES=$(mainwpctl abilities run list-updates-v1 --json 2>/dev/null) +UPDATES=$(mainwpcontrol abilities run list-updates-v1 --json 2>/dev/null) if [ $? -eq 0 ]; then PENDING=$(echo "$UPDATES" | jq '.data.data.total // 0') send_metric "mainwp.updates.pending:${PENDING}|g" @@ -475,7 +475,7 @@ send_metric() { } # Site count and disconnected count -SITES=$(mainwpctl abilities run list-sites-v1 --json 2>/dev/null) +SITES=$(mainwpcontrol abilities run list-sites-v1 --json 2>/dev/null) if [ $? -eq 0 ]; then TOTAL=$(echo "$SITES" | jq '.data.data.items | length') DISCONNECTED=$(echo "$SITES" | jq '[.data.data.items[] | select(.status != "connected")] | length') @@ -486,7 +486,7 @@ else fi # Pending updates -UPDATES=$(mainwpctl abilities run list-updates-v1 --json 2>/dev/null) +UPDATES=$(mainwpcontrol abilities run list-updates-v1 --json 2>/dev/null) if [ $? -eq 0 ]; then PENDING=$(echo "$UPDATES" | jq '.data.data.total // 0') send_metric "mainwp.updates.pending:${PENDING}|g" @@ -573,7 +573,7 @@ Run through this checklist to confirm everything is connected: 3. **If using Datadog:** Open Metrics Explorer and search for `mainwp`. You should see your metrics listed with recent data points. -4. **If you do not see metrics**, test the StatsD connection directly to rule out mainwpctl as the problem: +4. **If you do not see metrics**, test the StatsD connection directly to rule out mainwpcontrol as the problem: ```bash echo "test.metric:1|g" | nc -u -w1 localhost 8125 @@ -585,7 +585,7 @@ Run through this checklist to confirm everything is connected: ## Adapting for Other Monitoring Tools -The metrics-extraction commands (`mainwpctl` + `jq`) are the same regardless of where you send the data. Only the "send" step changes. +The metrics-extraction commands (`mainwpcontrol` + `jq`) are the same regardless of where you send the data. Only the "send" step changes. ### Prometheus / Node Exporter @@ -661,13 +661,13 @@ This appends a timestamped line to the log file each time the script runs. The ` Test the jq parsing in isolation to see what value is being extracted: ```bash -mainwpctl abilities run list-sites-v1 --json | jq '.data.data.items | length' +mainwpcontrol abilities run list-sites-v1 --json | jq '.data.data.items | length' ``` If the output is empty or shows a jq error, the JSON structure may have changed. Check the raw output: ```bash -mainwpctl abilities run list-sites-v1 --json +mainwpcontrol abilities run list-sites-v1 --json ``` Look at the actual structure and adjust the jq expressions accordingly. @@ -678,7 +678,7 @@ Look at the actual structure and adjust the jq expressions accordingly. - On Linux: `grep CRON /var/log/syslog` - On macOS: `log show --predicate 'process == "cron"' --last 1h` -- **Use full paths in cron.** Cron does not load your shell profile, so commands like `mainwpctl` and `jq` may not be found by their short names. Add a `PATH` line at the top of your crontab: +- **Use full paths in cron.** Cron does not load your shell profile, so commands like `mainwpcontrol` and `jq` may not be found by their short names. Add a `PATH` line at the top of your crontab: ``` PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin diff --git a/docs/workflows/monthly-batch-updates.md b/docs/workflows/monthly-batch-updates.md index 3bcaad0..34f829a 100644 --- a/docs/workflows/monthly-batch-updates.md +++ b/docs/workflows/monthly-batch-updates.md @@ -39,7 +39,7 @@ To create one: 1. Log in to the WordPress site where MainWP Dashboard is installed. 2. Go to **Users** in the left sidebar, then click on your own user profile (or go to **Users > Your Profile**). 3. Scroll down to the **Application Passwords** section near the bottom of the page. -4. In the **New Application Password Name** field, type a descriptive name like `mainwpctl`. +4. In the **New Application Password Name** field, type a descriptive name like `mainwpcontrol`. 5. Click **Add New Application Password**. 6. WordPress will display the generated password. It looks something like this: @@ -60,12 +60,12 @@ Install MainWP Control globally using npm (the Node.js package manager that come npm install -g @mainwp/control ``` -This makes the `mainwpctl` command available anywhere on your system. +This makes the `mainwpcontrol` command available anywhere on your system. If you prefer not to install globally, you can use `npx` to run it without a permanent install: ```bash -npx mainwpctl --version +npx --package=@mainwp/control mainwpcontrol --version ``` `npx` downloads and runs the package on the fly, which is useful for one-off testing. For scripting and automation, the global install is more convenient. @@ -73,16 +73,16 @@ npx mainwpctl --version Verify the installation: ```bash -mainwpctl --version +mainwpcontrol --version ``` Expected output: ``` -mainwpctl/x.y.z +mainwpcontrol/x.y.z ``` -You should see `mainwpctl/` followed by a version number. As long as the output starts with `mainwpctl/`, the installation is working. +You should see `mainwpcontrol/` followed by a version number. As long as the output starts with `mainwpcontrol/`, the installation is working. If you see `command not found`, make sure Node.js 20+ is installed and that your system PATH includes the npm global bin directory. Run `npm config get prefix` to find where npm installs global packages. @@ -93,7 +93,7 @@ If you see `command not found`, make sure Node.js 20+ is installed and that your Run the interactive login command: ```bash -mainwpctl login +mainwpcontrol login ``` MainWP Control will prompt you for three pieces of information: @@ -107,7 +107,7 @@ After entering your credentials, MainWP Control stores them in a local profile s Verify that authentication is working: ```bash -mainwpctl doctor +mainwpcontrol doctor ``` Expected output: @@ -136,7 +136,7 @@ Expected output: ✓ System is ready ``` -The key line is `✓ System is ready`. If any check fails, run `mainwpctl doctor -v` for details. If authentication fails, double-check your Dashboard URL, username, and Application Password. +The key line is `✓ System is ready`. If any check fails, run `mainwpcontrol doctor -v` for details. If authentication fails, double-check your Dashboard URL, username, and Application Password. --- @@ -176,7 +176,7 @@ This section builds a bash script step by step. Each step introduces one concept Start by asking MainWP what updates are available across all your connected sites: ```bash -mainwpctl abilities run list-updates-v1 --json +mainwpcontrol abilities run list-updates-v1 --json ``` Breaking this command down: @@ -226,7 +226,7 @@ The `data.data.total` field tells you how many updates are pending (the inner `d Now check what updates are available. `list-updates-v1` is a read-only ability. It shows you what is pending without changing anything: ```bash -PREVIEW=$(mainwpctl abilities run list-updates-v1 --json) +PREVIEW=$(mainwpcontrol abilities run list-updates-v1 --json) echo "$PREVIEW" ``` @@ -271,7 +271,7 @@ This tells you exactly what updates are pending: which sites, which plugins/them Next, extract the update count using `jq`. `jq` is a command-line tool for reading and manipulating JSON data. If you do not have it installed, you can install it with `brew install jq` on macOS or `sudo apt-get install jq` on Ubuntu/Debian: ```bash -PREVIEW=$(mainwpctl abilities run list-updates-v1 --json) +PREVIEW=$(mainwpcontrol abilities run list-updates-v1 --json) UPDATE_COUNT=$(echo "$PREVIEW" | jq '.data.data.total // 0') echo "$UPDATE_COUNT updates pending" ``` @@ -289,7 +289,7 @@ Expected output: When you are satisfied with the preview, apply the updates for real: ```bash -mainwpctl abilities run run-updates-v1 --confirm --force --wait --json +mainwpcontrol abilities run run-updates-v1 --confirm --force --wait --json ``` Here is what each flag does in this context: @@ -333,7 +333,7 @@ The output shows how many updates succeeded and how many failed, along with per- After applying updates, check that nothing is left pending: ```bash -REMAINING=$(mainwpctl abilities run list-updates-v1 --json | jq '.data.data.total // 0') +REMAINING=$(mainwpcontrol abilities run list-updates-v1 --json | jq '.data.data.total // 0') echo "$REMAINING updates remaining after run" ``` @@ -361,7 +361,7 @@ set -e # Step 1: Preview what will be updated (nothing changes yet) echo "Previewing pending updates..." -PREVIEW=$(mainwpctl abilities run list-updates-v1 --json) +PREVIEW=$(mainwpcontrol abilities run list-updates-v1 --json) # Step 2: Check how many updates are pending UPDATE_COUNT=$(echo "$PREVIEW" | jq '.data.data.total // 0') @@ -374,10 +374,10 @@ fi # Step 3: Apply updates and wait for them to finish echo "Applying $UPDATE_COUNT updates..." -mainwpctl abilities run run-updates-v1 --confirm --force --wait --json +mainwpcontrol abilities run run-updates-v1 --confirm --force --wait --json # Step 4: Verify no updates remain -REMAINING=$(mainwpctl abilities run list-updates-v1 --json | jq '.data.data.total // 0') +REMAINING=$(mainwpcontrol abilities run list-updates-v1 --json | jq '.data.data.total // 0') echo "$REMAINING updates remaining after run" ``` @@ -524,12 +524,12 @@ jobs: ```yaml - name: Login run: > - mainwpctl login + mainwpcontrol login --url $DASHBOARD_URL --username $DASHBOARD_USER ``` -- `env`: Sets job-level environment variables so every `mainwpctl` step can authenticate. GitHub runners often do not persist credentials in an OS keychain between steps, so `MAINWP_APP_PASSWORD` must stay available for the whole job. +- `env`: Sets job-level environment variables so every `mainwpcontrol` step can authenticate. GitHub runners often do not persist credentials in an OS keychain between steps, so `MAINWP_APP_PASSWORD` must stay available for the whole job. - `${{ secrets.DASHBOARD_URL }}`: GitHub replaces this with the encrypted secret value at runtime. The actual value never appears in logs. - The `>` after `run:` is YAML syntax for a folded string. It joins the following indented lines into a single command, which makes long commands easier to read. @@ -539,7 +539,7 @@ jobs: - name: Preview updates id: preview run: | - PREVIEW=$(mainwpctl abilities run list-updates-v1 --json) + PREVIEW=$(mainwpcontrol abilities run list-updates-v1 --json) COUNT=$(echo "$PREVIEW" | jq '.data.data.total // 0') echo "count=$COUNT" >> "$GITHUB_OUTPUT" echo "### Preview: $COUNT updates pending" >> "$GITHUB_STEP_SUMMARY" @@ -555,7 +555,7 @@ jobs: - name: Apply updates if: steps.preview.outputs.count != '0' run: > - mainwpctl abilities run run-updates-v1 + mainwpcontrol abilities run run-updates-v1 --confirm --force --wait --json ``` @@ -568,7 +568,7 @@ jobs: - name: Verify if: steps.preview.outputs.count != '0' run: | - REMAINING=$(mainwpctl abilities run list-updates-v1 --json | jq '.data.data.total // 0') + REMAINING=$(mainwpcontrol abilities run list-updates-v1 --json | jq '.data.data.total // 0') echo "### $REMAINING updates remaining after run" >> "$GITHUB_STEP_SUMMARY" ``` @@ -602,14 +602,14 @@ jobs: - name: Login run: > - mainwpctl login + mainwpcontrol login --url $DASHBOARD_URL --username $DASHBOARD_USER - name: Preview updates id: preview run: | - PREVIEW=$(mainwpctl abilities run list-updates-v1 --json) + PREVIEW=$(mainwpcontrol abilities run list-updates-v1 --json) COUNT=$(echo "$PREVIEW" | jq '.data.data.total // 0') echo "count=$COUNT" >> "$GITHUB_OUTPUT" echo "### Preview: $COUNT updates pending" >> "$GITHUB_STEP_SUMMARY" @@ -617,13 +617,13 @@ jobs: - name: Apply updates if: steps.preview.outputs.count != '0' run: > - mainwpctl abilities run run-updates-v1 + mainwpcontrol abilities run run-updates-v1 --confirm --force --wait --json - name: Verify if: steps.preview.outputs.count != '0' run: | - REMAINING=$(mainwpctl abilities run list-updates-v1 --json | jq '.data.data.total // 0') + REMAINING=$(mainwpcontrol abilities run list-updates-v1 --json | jq '.data.data.total // 0') echo "### $REMAINING updates remaining after run" >> "$GITHUB_STEP_SUMMARY" ``` @@ -681,7 +681,7 @@ The default wait timeout is 300 seconds (5 minutes). For large networks with man To increase the timeout, add the `--wait-timeout` flag with a value in seconds: ```bash -mainwpctl abilities run run-updates-v1 --confirm --force --wait --wait-timeout 600 --json +mainwpcontrol abilities run run-updates-v1 --confirm --force --wait --wait-timeout 600 --json ``` This increases the timeout to 10 minutes (600 seconds). @@ -689,7 +689,7 @@ This increases the timeout to 10 minutes (600 seconds). If the command still times out, the updates are not cancelled. They continue running on the MainWP server. The CLI stops waiting. You can check the progress of a running job with: ```bash -mainwpctl jobs watch +mainwpcontrol jobs watch ``` Replace `` with the job ID from the timeout output. This command connects to the job and shows its progress until it finishes. @@ -703,7 +703,7 @@ To see which updates failed, check the `results` array in the JSON output. Each To see what is still pending after a run: ```bash -mainwpctl abilities run list-updates-v1 --json +mainwpcontrol abilities run list-updates-v1 --json ``` ### "Updates remaining" Shows a Non-Zero Count After Running @@ -722,7 +722,7 @@ The `set -e` directive tells bash to stop the script immediately if any command To debug, run each command from the script individually in your terminal to find which one is failing and why. Common causes: - `jq` is not installed (install it with `brew install jq` or `sudo apt-get install jq`) -- MainWP Control is not authenticated (run `mainwpctl doctor` to check) +- MainWP Control is not authenticated (run `mainwpcontrol doctor` to check) - A network error caused a non-zero exit code ### GitHub Actions: "Login Failed" diff --git a/docs/workflows/plugin-deployment-verification.md b/docs/workflows/plugin-deployment-verification.md index ae6648b..1f44996 100644 --- a/docs/workflows/plugin-deployment-verification.md +++ b/docs/workflows/plugin-deployment-verification.md @@ -40,7 +40,7 @@ An **Application Password** is a special password that WordPress generates for e 1. Log in to your WordPress Dashboard site (the site where MainWP Dashboard is installed). 2. In the left sidebar, go to **Users** then click **Your Profile** (or **Profile**). 3. Scroll down to the section titled **Application Passwords**. -4. In the **New Application Password Name** field, type a descriptive name such as `mainwpctl`. +4. In the **New Application Password Name** field, type a descriptive name such as `mainwpcontrol`. 5. Click **Add New Application Password**. 6. WordPress displays the generated password. It looks something like this: @@ -65,31 +65,31 @@ Install MainWP Control globally using npm (npm is the package manager that comes npm install -g @mainwp/control ``` -This downloads MainWP Control and makes the `mainwpctl` command available anywhere on your machine. +This downloads MainWP Control and makes the `mainwpcontrol` command available anywhere on your machine. **Alternative -- run without installing globally:** If you prefer not to install globally, you can use `npx` which runs the package directly: ```bash -npx mainwpctl --version +npx --package=@mainwp/control mainwpcontrol --version ``` -`npx` downloads the package temporarily each time you run it. For this guide, the examples use `mainwpctl` directly, but you can substitute `npx mainwpctl` anywhere you see `mainwpctl`. +`npx` downloads the package temporarily each time you run it. For this guide, the examples use `mainwpcontrol` directly, but you can substitute `npx --package=@mainwp/control mainwpcontrol` anywhere you see `mainwpcontrol`. **Verify the installation:** ```bash -mainwpctl --version +mainwpcontrol --version ``` Expected output: ``` -mainwpctl/x.y.z darwin-arm64 node-vNN.NN.N +mainwpcontrol/x.y.z darwin-arm64 node-vNN.NN.N ``` -You should see `mainwpctl/` followed by a version number. If you see `command not found`, make sure Node.js 20+ is installed and try opening a new terminal window. +You should see `mainwpcontrol/` followed by a version number. If you see `command not found`, make sure Node.js 20+ is installed and try opening a new terminal window. --- @@ -100,7 +100,7 @@ Before setting up GitHub Actions, verify that your credentials work by logging i Run the interactive login command: ```bash -mainwpctl login +mainwpcontrol login ``` MainWP Control will prompt you for three pieces of information: @@ -114,7 +114,7 @@ After entering your credentials, MainWP Control stores them in a local profile s **Verify the connection:** ```bash -mainwpctl doctor +mainwpcontrol doctor ``` Expected output: @@ -143,7 +143,7 @@ Expected output: ✓ System is ready ``` -The key line is `✓ System is ready`. If any check fails, run `mainwpctl doctor -v` for details. If authentication fails, double-check your URL (make sure it includes `https://`), username, and Application Password. +The key line is `✓ System is ready`. If any check fails, run `mainwpcontrol doctor -v` for details. If authentication fails, double-check your URL (make sure it includes `https://`), username, and Application Password. **Note:** The GitHub Actions workflow will use the same credentials, but it reads them from GitHub Secrets instead of a local profile. The next step sets that up. @@ -229,7 +229,7 @@ jobs: with: node-version: '20' - - name: Install mainwpctl + - name: Install mainwpcontrol run: npm install -g @mainwp/control ``` @@ -246,14 +246,14 @@ jobs: ```yaml - name: Authenticate run: > - mainwpctl login + mainwpcontrol login --url $DASHBOARD_URL --username $DASHBOARD_USER ``` -- `env:` sets job-level environment variables so every `mainwpctl` step can authenticate. GitHub runners often do not persist credentials in an OS keychain between steps, so `MAINWP_APP_PASSWORD` must stay available for the whole job. +- `env:` sets job-level environment variables so every `mainwpcontrol` step can authenticate. GitHub runners often do not persist credentials in an OS keychain between steps, so `MAINWP_APP_PASSWORD` must stay available for the whole job. - `${{ secrets.NAME }}` is GitHub Actions syntax for reading a secret. GitHub replaces this with the actual value at runtime and automatically masks it in logs. -- `run: >` uses a YAML feature called **folding**. The `>` character means "join the following indented lines into a single line." This lets you split a long command across multiple lines for readability. The actual command that runs is: `mainwpctl login --url $DASHBOARD_URL --username $DASHBOARD_USER` +- `run: >` uses a YAML feature called **folding**. The `>` character means "join the following indented lines into a single line." This lets you split a long command across multiple lines for readability. The actual command that runs is: `mainwpcontrol login --url $DASHBOARD_URL --username $DASHBOARD_USER` - The `--url` and `--username` flags provide credentials non-interactively, which is necessary because GitHub Actions runs without a terminal and cannot prompt for input. --- @@ -263,9 +263,9 @@ jobs: ```yaml - name: Check plugin across sites run: | - mainwpctl abilities run list-sites-v1 --json | \ + mainwpcontrol abilities run list-sites-v1 --json | \ jq -r '.data.data.items[].id' | while read SITE_ID; do - PLUGINS=$(mainwpctl abilities run get-site-plugins-v1 \ + PLUGINS=$(mainwpcontrol abilities run get-site-plugins-v1 \ --input "{\"site_id_or_domain\": $SITE_ID}" --json 2>/dev/null) SUCCESS=$(echo "$PLUGINS" | jq -r '.success // false') if [ "$SUCCESS" != "true" ]; then @@ -284,13 +284,13 @@ This is the core of the workflow. Here is what each piece does: - `run: |` uses a YAML **literal block**. The `|` character means "keep the following lines exactly as written, including line breaks." This is used for multi-line scripts. -- **`mainwpctl abilities run list-sites-v1 --json`** calls the MainWP API to fetch a list of all connected sites. The `--json` flag tells mainwpctl to output structured JSON instead of human-readable text. +- **`mainwpcontrol abilities run list-sites-v1 --json`** calls the MainWP API to fetch a list of all connected sites. The `--json` flag tells mainwpcontrol to output structured JSON instead of human-readable text. - **`jq -r '.data.data.items[].id'`** extracts the site IDs from the JSON response. `jq` is a command-line JSON processor (it comes pre-installed on GitHub's Ubuntu runners). The `-r` flag outputs raw text without quotes. `.data.data.items[].id` is a jq filter that means "from the outer `data` object, navigate into the inner `data` object, get the `items` array, and for each element, extract the `id` field." - **`| while read SITE_ID; do ... done`** is a shell loop. The `|` (pipe) sends the list of site IDs into the loop, which processes them one at a time. Each iteration stores one site ID in the variable `SITE_ID`. -- **`mainwpctl abilities run get-site-plugins-v1 --input "{\"site_id_or_domain\": $SITE_ID}" --json`** fetches the list of plugins installed on a specific site. The `--input` flag passes the site identifier as a JSON parameter. The backslashes (`\"`) are needed to include quotes inside the JSON string. +- **`mainwpcontrol abilities run get-site-plugins-v1 --input "{\"site_id_or_domain\": $SITE_ID}" --json`** fetches the list of plugins installed on a specific site. The `--input` flag passes the site identifier as a JSON parameter. The backslashes (`\"`) are needed to include quotes inside the JSON string. - **The error check** (`SUCCESS` / `continue`) handles sites that are disconnected or unreachable. If the plugins call fails, the script emits a warning and skips to the next site instead of crashing. @@ -327,20 +327,20 @@ jobs: with: node-version: '20' - - name: Install mainwpctl + - name: Install mainwpcontrol run: npm install -g @mainwp/control - name: Authenticate run: > - mainwpctl login + mainwpcontrol login --url $DASHBOARD_URL --username $DASHBOARD_USER - name: Check plugin across sites run: | - mainwpctl abilities run list-sites-v1 --json | \ + mainwpcontrol abilities run list-sites-v1 --json | \ jq -r '.data.data.items[].id' | while read SITE_ID; do - PLUGINS=$(mainwpctl abilities run get-site-plugins-v1 \ + PLUGINS=$(mainwpcontrol abilities run get-site-plugins-v1 \ --input "{\"site_id_or_domain\": $SITE_ID}" --json 2>/dev/null) SUCCESS=$(echo "$PLUGINS" | jq -r '.success // false') if [ "$SUCCESS" != "true" ]; then @@ -450,10 +450,10 @@ The `plugin` input uses the **plugin slug**, not the display name. The slug is t | Contact Form 7 | `contact-form-7` | | Wordfence Security | `wordfence` | -If you are unsure of a plugin's slug, you can check it using mainwpctl on your local machine: +If you are unsure of a plugin's slug, you can check it using mainwpcontrol on your local machine: ```bash -mainwpctl abilities run get-site-plugins-v1 \ +mainwpcontrol abilities run get-site-plugins-v1 \ --input '{"site_id_or_domain": 1}' \ --json | jq -r '.data.data.plugins[].slug' ``` diff --git a/package-lock.json b/package-lock.json index a88ee2e..99fb70b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,11 +13,10 @@ "@oclif/plugin-autocomplete": "~3.2.39", "@oclif/plugin-help": "~6.0.0", "ajv": "^8.18.0", - "keytar": "~7.9.0", "undici": "^7.24.0" }, "bin": { - "mainwpctl": "bin/run.js" + "mainwpcontrol": "bin/run.js" }, "devDependencies": { "@oclif/test": "^4.0.0", @@ -31,6 +30,9 @@ }, "engines": { "node": ">=20.0.0" + }, + "optionalDependencies": { + "keytar": "~7.9.0" } }, "node_modules/@aws-crypto/crc32": { @@ -4579,13 +4581,15 @@ "url": "https://feross.org/support" } ], - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "license": "MIT", + "optional": true, "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -4639,6 +4643,7 @@ } ], "license": "MIT", + "optional": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -4821,7 +4826,8 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "license": "ISC" + "license": "ISC", + "optional": true }, "node_modules/clean-stack": { "version": "3.0.1", @@ -4995,6 +5001,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "devOptional": true, "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" @@ -5010,6 +5017,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "devOptional": true, "license": "MIT", "engines": { "node": ">=10" @@ -5036,6 +5044,7 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "license": "MIT", + "optional": true, "engines": { "node": ">=4.0.0" } @@ -5075,6 +5084,7 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", + "optional": true, "engines": { "node": ">=8" } @@ -5164,6 +5174,7 @@ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "license": "MIT", + "optional": true, "dependencies": { "once": "^1.4.0" } @@ -5506,6 +5517,7 @@ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "license": "(MIT OR WTFPL)", + "optional": true, "engines": { "node": ">=6" } @@ -5742,7 +5754,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/fs-extra": { "version": "8.1.0", @@ -5840,7 +5853,8 @@ "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/github-slugger": { "version": "2.0.0", @@ -6123,7 +6137,8 @@ "url": "https://feross.org/support" } ], - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "optional": true }, "node_modules/ignore": { "version": "5.3.2", @@ -6186,12 +6201,14 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "devOptional": true, "license": "ISC" }, "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "devOptional": true, "license": "ISC" }, "node_modules/is-arrayish": { @@ -6399,6 +6416,7 @@ "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", "hasInstallScript": true, "license": "MIT", + "optional": true, "dependencies": { "node-addon-api": "^4.3.0", "prebuild-install": "^7.0.1" @@ -6612,6 +6630,7 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "license": "MIT", + "optional": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6620,7 +6639,8 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/mlly": { "version": "1.8.0", @@ -6681,7 +6701,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/natural-compare": { "version": "1.4.0", @@ -6715,6 +6736,7 @@ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", "license": "MIT", + "optional": true, "dependencies": { "semver": "^7.3.5" }, @@ -6726,7 +6748,8 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/normalize-package-data": { "version": "6.0.2", @@ -6919,6 +6942,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "devOptional": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -7219,6 +7243,7 @@ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", "license": "MIT", + "optional": true, "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", @@ -7290,6 +7315,7 @@ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", "license": "MIT", + "optional": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -7343,6 +7369,7 @@ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -7358,6 +7385,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "license": "MIT", + "optional": true, "engines": { "node": ">=0.10.0" } @@ -7374,6 +7402,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", + "optional": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -7556,6 +7585,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "devOptional": true, "funding": [ { "type": "github", @@ -7662,7 +7692,8 @@ "url": "https://feross.org/support" } ], - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/simple-get": { "version": "4.0.1", @@ -7683,6 +7714,7 @@ } ], "license": "MIT", + "optional": true, "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", @@ -7839,6 +7871,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "license": "MIT", + "optional": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -7966,6 +7999,7 @@ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "license": "MIT", + "optional": true, "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -7978,6 +8012,7 @@ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "license": "MIT", + "optional": true, "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -8114,6 +8149,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "devOptional": true, "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" @@ -8237,7 +8273,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/validate-npm-package-license": { "version": "3.0.4", @@ -8490,6 +8527,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "devOptional": true, "license": "ISC" }, "node_modules/yocto-queue": { diff --git a/package.json b/package.json index eac4704..1fd0518 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "exports": "./dist/index.js", "types": "./dist/index.d.ts", "bin": { - "mainwpctl": "./bin/run.js" + "mainwpcontrol": "./bin/run.js" }, "files": [ "bin", @@ -32,8 +32,8 @@ "pack:deb": "oclif pack deb" }, "oclif": { - "bin": "mainwpctl", - "dirname": "mainwpctl", + "bin": "mainwpcontrol", + "dirname": "mainwpcontrol", "commands": "./dist/commands", "default": "chat", "plugins": [ @@ -42,11 +42,11 @@ ], "topicSeparator": " ", "macos": { - "identifier": "com.mainwp.mainwpctl" + "identifier": "com.mainwp.mainwpcontrol" }, "update": { "s3": { - "bucket": "mainwpctl-releases" + "bucket": "mainwpcontrol-releases" } } }, diff --git a/scripts/completions/README.md b/scripts/completions/README.md index 86e8593..0d9faee 100644 --- a/scripts/completions/README.md +++ b/scripts/completions/README.md @@ -1,6 +1,6 @@ # Shell Completion for MainWP Control -This directory contains shell completion scripts for `mainwpctl`, providing tab completion for commands, flags, and dynamic data like profile names. +This directory contains shell completion scripts for `mainwpcontrol`, providing tab completion for commands, flags, and dynamic data like profile names. ## Quick Start @@ -9,7 +9,7 @@ This directory contains shell completion scripts for `mainwpctl`, providing tab Add to your `~/.bashrc`: ```bash -source /path/to/mainwpctl/scripts/completions/mainwpctl.bash +source /path/to/mainwp-control/scripts/completions/mainwpcontrol.bash ``` Then reload your shell: @@ -23,7 +23,7 @@ source ~/.bashrc Add to your `~/.zshrc`: ```bash -source /path/to/mainwpctl/scripts/completions/mainwpctl.zsh +source /path/to/mainwp-control/scripts/completions/mainwpcontrol.zsh ``` Then reload your shell: @@ -34,17 +34,17 @@ source ~/.zshrc ## For npm-installed CLI -If you installed `mainwpctl` globally via npm: +If you installed `mainwpcontrol` globally via npm: ```bash # Find the installation path npm root -g # Source from node_modules (bash example) -source $(npm root -g)/mainwpctl/scripts/completions/mainwpctl.bash +source $(npm root -g)/@mainwp/control/scripts/completions/mainwpcontrol.bash # Or for zsh -source $(npm root -g)/mainwpctl/scripts/completions/mainwpctl.zsh +source $(npm root -g)/@mainwp/control/scripts/completions/mainwpcontrol.zsh ``` ## For Local Development @@ -53,10 +53,10 @@ If you're developing from the cloned repository: ```bash # Bash -source ./scripts/completions/mainwpctl.bash +source ./scripts/completions/mainwpcontrol.bash # Zsh -source ./scripts/completions/mainwpctl.zsh +source ./scripts/completions/mainwpcontrol.zsh ``` ## What's Completed @@ -129,7 +129,7 @@ Profile names are completed dynamically for: - `profile use ` argument - `profile delete ` argument -Profile names are read from `~/.config/mainwpctl/profiles.json`. +Profile names are read from `~/.config/mainwpcontrol/profiles.json`. ## Updating Completions @@ -145,8 +145,8 @@ This provides guidance on which files to update. | File | Purpose | |------|---------| -| `mainwpctl.bash` | Bash completion script | -| `mainwpctl.zsh` | Zsh completion script | +| `mainwpcontrol.bash` | Bash completion script | +| `mainwpcontrol.zsh` | Zsh completion script | | `profile-completer.sh` | Helper to read profile names from config | | `regenerate.sh` | Helper script for updating completions | | `README.md` | This documentation | @@ -158,10 +158,10 @@ This provides guidance on which files to update. 1. **Check if sourced correctly:** ```bash # Bash - complete -p mainwpctl + complete -p mainwpcontrol # Zsh - whence -f _mainwpctl + whence -f _mainwpcontrol ``` 2. **Reload shell configuration:** @@ -180,7 +180,7 @@ This provides guidance on which files to update. 1. **Check if profiles.json exists:** ```bash - cat ~/.config/mainwpctl/profiles.json + cat ~/.config/mainwpcontrol/profiles.json ``` 2. **Check if jq is installed (optional but recommended):** @@ -210,8 +210,8 @@ Make sure completion scripts are executable: ```bash chmod +x scripts/completions/*.sh -chmod +x scripts/completions/mainwpctl.bash -chmod +x scripts/completions/mainwpctl.zsh +chmod +x scripts/completions/mainwpcontrol.bash +chmod +x scripts/completions/mainwpcontrol.zsh ``` ## Requirements diff --git a/scripts/completions/mainwpctl.bash b/scripts/completions/mainwpcontrol.bash similarity index 92% rename from scripts/completions/mainwpctl.bash rename to scripts/completions/mainwpcontrol.bash index bb5a454..0b4e709 100755 --- a/scripts/completions/mainwpctl.bash +++ b/scripts/completions/mainwpcontrol.bash @@ -1,11 +1,11 @@ #!/bin/bash -# mainwpctl bash completion script +# mainwpcontrol bash completion script # # Installation: -# source /path/to/mainwpctl/scripts/completions/mainwpctl.bash +# source /path/to/mainwpcontrol/scripts/completions/mainwpcontrol.bash # # Or add to ~/.bashrc: -# source /path/to/mainwpctl/scripts/completions/mainwpctl.bash +# source /path/to/mainwpcontrol/scripts/completions/mainwpcontrol.bash # Determine the directory where this script is located _MAINWPCTL_COMPLETION_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -15,7 +15,7 @@ if [[ -f "${_MAINWPCTL_COMPLETION_DIR}/profile-completer.sh" ]]; then source "${_MAINWPCTL_COMPLETION_DIR}/profile-completer.sh" fi -_mainwpctl_completions() { +_mainwpcontrol_completions() { local cur prev words cword _init_completion -n : || return @@ -71,8 +71,8 @@ _mainwpctl_completions() { --profile|-p) # Complete with profile names local profiles - if type _mainwpctl_get_profiles &>/dev/null; then - profiles=$(_mainwpctl_get_profiles) + if type _mainwpcontrol_get_profiles &>/dev/null; then + profiles=$(_mainwpcontrol_get_profiles) COMPREPLY=($(compgen -W "$profiles" -- "$cur")) fi return 0 @@ -163,8 +163,8 @@ _mainwpctl_completions() { # Complete with profile names for these subcommands if [[ "$cur" != -* ]]; then local profiles - if type _mainwpctl_get_profiles &>/dev/null; then - profiles=$(_mainwpctl_get_profiles) + if type _mainwpcontrol_get_profiles &>/dev/null; then + profiles=$(_mainwpcontrol_get_profiles) COMPREPLY=($(compgen -W "$profiles" -- "$cur")) fi else @@ -190,4 +190,4 @@ _mainwpctl_completions() { } # Register the completion function -complete -F _mainwpctl_completions mainwpctl +complete -F _mainwpcontrol_completions mainwpcontrol diff --git a/scripts/completions/mainwpctl.zsh b/scripts/completions/mainwpcontrol.zsh similarity index 84% rename from scripts/completions/mainwpctl.zsh rename to scripts/completions/mainwpcontrol.zsh index c435512..8d24ac5 100755 --- a/scripts/completions/mainwpctl.zsh +++ b/scripts/completions/mainwpcontrol.zsh @@ -1,11 +1,11 @@ -#compdef mainwpctl -# mainwpctl zsh completion script +#compdef mainwpcontrol +# mainwpcontrol zsh completion script # # Installation: -# source /path/to/mainwpctl/scripts/completions/mainwpctl.zsh +# source /path/to/mainwpcontrol/scripts/completions/mainwpcontrol.zsh # # Or add to ~/.zshrc: -# source /path/to/mainwpctl/scripts/completions/mainwpctl.zsh +# source /path/to/mainwpcontrol/scripts/completions/mainwpcontrol.zsh # Determine the directory where this script is located _MAINWPCTL_COMPLETION_DIR="${0:A:h}" @@ -16,16 +16,16 @@ if [[ -f "${_MAINWPCTL_COMPLETION_DIR}/profile-completer.sh" ]]; then fi # Helper function to get profile names for completion -_mainwpctl_profiles() { +_mainwpcontrol_profiles() { local profiles - if (( $+functions[_mainwpctl_get_profiles] )); then - profiles=("${(@f)$(_mainwpctl_get_profiles)}") + if (( $+functions[_mainwpcontrol_get_profiles] )); then + profiles=("${(@f)$(_mainwpcontrol_get_profiles)}") _describe -t profiles 'profile' profiles fi } # Main completion function -_mainwpctl() { +_mainwpcontrol() { local curcontext="$curcontext" state line typeset -A opt_args @@ -35,7 +35,7 @@ _mainwpctl() { '--debug[Show debug output]' '--help[Show help]' '--json[Output JSON (for scripting/CI)]' - '(-p --profile)'{-p,--profile}'[Use a specific profile]:profile:_mainwpctl_profiles' + '(-p --profile)'{-p,--profile}'[Use a specific profile]:profile:_mainwpcontrol_profiles' ) # Top-level commands @@ -58,33 +58,33 @@ _mainwpctl() { case "$state" in command) - _describe -t commands 'mainwpctl commands' commands + _describe -t commands 'mainwpcontrol commands' commands ;; args) case "$words[1]" in abilities) - _mainwpctl_abilities + _mainwpcontrol_abilities ;; autocomplete) - _mainwpctl_autocomplete + _mainwpcontrol_autocomplete ;; chat) - _mainwpctl_chat + _mainwpcontrol_chat ;; doctor) - _mainwpctl_doctor + _mainwpcontrol_doctor ;; help) - _mainwpctl_help + _mainwpcontrol_help ;; jobs) - _mainwpctl_jobs + _mainwpcontrol_jobs ;; login) - _mainwpctl_login + _mainwpcontrol_login ;; profile) - _mainwpctl_profile + _mainwpcontrol_profile ;; esac ;; @@ -92,7 +92,7 @@ _mainwpctl() { } # Abilities command completions -_mainwpctl_abilities() { +_mainwpcontrol_abilities() { local -a subcommands subcommands=( 'info:Get detailed information about an ability' @@ -136,13 +136,13 @@ _mainwpctl_abilities() { } # Autocomplete command completions -_mainwpctl_autocomplete() { +_mainwpcontrol_autocomplete() { _arguments \ '1:shell:(bash zsh)' } # Chat command completions -_mainwpctl_chat() { +_mainwpcontrol_chat() { _arguments \ $common_flags \ '--provider[LLM provider]:provider:(anthropic gemini local openai openrouter)' \ @@ -157,14 +157,14 @@ _mainwpctl_chat() { } # Doctor command completions -_mainwpctl_doctor() { +_mainwpcontrol_doctor() { _arguments \ $common_flags \ '(-v --verbose)'{-v,--verbose}'[Verbose output]' } # Help command completions -_mainwpctl_help() { +_mainwpcontrol_help() { local -a commands commands=( 'abilities' @@ -182,7 +182,7 @@ _mainwpctl_help() { } # Jobs command completions -_mainwpctl_jobs() { +_mainwpcontrol_jobs() { local -a subcommands subcommands=( 'watch:Monitor a batch job' @@ -214,7 +214,7 @@ _mainwpctl_jobs() { } # Login command completions -_mainwpctl_login() { +_mainwpcontrol_login() { _arguments \ $common_flags \ '(-u --url)'{-u,--url}'[Dashboard URL]:url:' \ @@ -225,7 +225,7 @@ _mainwpctl_login() { } # Profile command completions -_mainwpctl_profile() { +_mainwpcontrol_profile() { local -a subcommands subcommands=( 'delete:Delete a profile' @@ -247,7 +247,7 @@ _mainwpctl_profile() { delete) _arguments \ $common_flags \ - '1:profile name:_mainwpctl_profiles' + '1:profile name:_mainwpcontrol_profiles' ;; list) _arguments \ @@ -256,7 +256,7 @@ _mainwpctl_profile() { use) _arguments \ $common_flags \ - '1:profile name:_mainwpctl_profiles' + '1:profile name:_mainwpcontrol_profiles' ;; esac ;; @@ -264,4 +264,4 @@ _mainwpctl_profile() { } # Register the completion function -compdef _mainwpctl mainwpctl +compdef _mainwpcontrol mainwpcontrol diff --git a/scripts/completions/profile-completer.sh b/scripts/completions/profile-completer.sh index 67b0742..03c806d 100755 --- a/scripts/completions/profile-completer.sh +++ b/scripts/completions/profile-completer.sh @@ -1,13 +1,13 @@ #!/bin/sh -# profile-completer.sh - Helper script to get available mainwpctl profile names +# profile-completer.sh - Helper script to get available mainwpcontrol profile names # This script is sourced by shell completion scripts to provide dynamic profile completion. # -# Usage: source this file, then call _mainwpctl_get_profiles +# Usage: source this file, then call _mainwpcontrol_get_profiles # # Returns profile names one per line, empty if no profiles exist or config is missing. -_mainwpctl_get_profiles() { - local config_file="${XDG_CONFIG_HOME:-$HOME/.config}/mainwpctl/profiles.json" +_mainwpcontrol_get_profiles() { + local config_file="${XDG_CONFIG_HOME:-$HOME/.config}/mainwpcontrol/profiles.json" # Exit silently if config file doesn't exist if [ ! -f "$config_file" ]; then @@ -31,5 +31,5 @@ _mainwpctl_get_profiles() { # If called directly (not sourced), output profile names if [ "${0##*/}" = "profile-completer.sh" ]; then - _mainwpctl_get_profiles + _mainwpcontrol_get_profiles fi diff --git a/scripts/completions/regenerate.sh b/scripts/completions/regenerate.sh index bba61ad..b151f8b 100755 --- a/scripts/completions/regenerate.sh +++ b/scripts/completions/regenerate.sh @@ -1,5 +1,5 @@ #!/bin/bash -# regenerate.sh - Regenerate shell completion scripts for mainwpctl +# regenerate.sh - Regenerate shell completion scripts for mainwpcontrol # # This script helps developers update completion scripts after CLI changes. # Run this after adding, removing, or modifying commands or flags. @@ -14,44 +14,44 @@ PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" echo "Shell Completion Regeneration Helper" echo "=====================================" echo "" -echo "The mainwpctl completion scripts are manually maintained to provide" +echo "The mainwpcontrol completion scripts are manually maintained to provide" echo "optimal completion behavior with dynamic profile name completion." echo "" echo "After adding, removing, or modifying commands/flags, you should update:" echo "" -echo " 1. $SCRIPT_DIR/mainwpctl.bash" +echo " 1. $SCRIPT_DIR/mainwpcontrol.bash" echo " - Update 'commands' variable for new top-level commands" echo " - Update '*_commands' variables for new subcommands" echo " - Update '*_flags' variables for new flags" echo "" -echo " 2. $SCRIPT_DIR/mainwpctl.zsh" +echo " 2. $SCRIPT_DIR/mainwpcontrol.zsh" echo " - Update 'commands' array for new top-level commands" echo " - Update subcommand arrays in respective functions" echo " - Update _arguments calls for new flags" echo "" echo "Testing completions:" echo " # Bash" -echo " source $SCRIPT_DIR/mainwpctl.bash" -echo " mainwpctl " +echo " source $SCRIPT_DIR/mainwpcontrol.bash" +echo " mainwpcontrol " echo "" echo " # Zsh" -echo " source $SCRIPT_DIR/mainwpctl.zsh" -echo " mainwpctl " +echo " source $SCRIPT_DIR/mainwpcontrol.zsh" +echo " mainwpcontrol " echo "" # Verify files exist echo "Checking completion files..." -if [[ -f "$SCRIPT_DIR/mainwpctl.bash" ]]; then - echo " [OK] mainwpctl.bash" +if [[ -f "$SCRIPT_DIR/mainwpcontrol.bash" ]]; then + echo " [OK] mainwpcontrol.bash" else - echo " [MISSING] mainwpctl.bash" + echo " [MISSING] mainwpcontrol.bash" fi -if [[ -f "$SCRIPT_DIR/mainwpctl.zsh" ]]; then - echo " [OK] mainwpctl.zsh" +if [[ -f "$SCRIPT_DIR/mainwpcontrol.zsh" ]]; then + echo " [OK] mainwpcontrol.zsh" else - echo " [MISSING] mainwpctl.zsh" + echo " [MISSING] mainwpcontrol.zsh" fi if [[ -f "$SCRIPT_DIR/profile-completer.sh" ]]; then diff --git a/src/__tests__/e2e/command-workflows.test.ts b/src/__tests__/e2e/command-workflows.test.ts index e86fdfd..9aaf295 100644 --- a/src/__tests__/e2e/command-workflows.test.ts +++ b/src/__tests__/e2e/command-workflows.test.ts @@ -233,10 +233,10 @@ function createCommandWithCapture const mockConfig = { root: '/mock/root', - bin: 'mainwpctl', - name: 'mainwpctl', + bin: 'mainwpcontrol', + name: 'mainwpcontrol', version: '1.0.0', - pjson: { name: 'mainwpctl', version: '1.0.0' }, + pjson: { name: 'mainwpcontrol', version: '1.0.0' }, dataDir: '/mock/data', cacheDir: '/mock/cache', configDir: '/mock/config', diff --git a/src/__tests__/e2e/exit-codes.test.ts b/src/__tests__/e2e/exit-codes.test.ts index 340e7b1..284580e 100644 --- a/src/__tests__/e2e/exit-codes.test.ts +++ b/src/__tests__/e2e/exit-codes.test.ts @@ -125,10 +125,10 @@ function createRunCommand( const mockConfig = { root: '/mock/root', - bin: 'mainwpctl', - name: 'mainwpctl', + bin: 'mainwpcontrol', + name: 'mainwpcontrol', version: '1.0.0', - pjson: { name: 'mainwpctl', version: '1.0.0' }, + pjson: { name: 'mainwpcontrol', version: '1.0.0' }, dataDir: '/mock/data', cacheDir: '/mock/cache', configDir: '/mock/config', diff --git a/src/__tests__/e2e/json-contract.test.ts b/src/__tests__/e2e/json-contract.test.ts index fe179b0..45496d7 100644 --- a/src/__tests__/e2e/json-contract.test.ts +++ b/src/__tests__/e2e/json-contract.test.ts @@ -118,10 +118,10 @@ function createCommand( const mockConfig = { root: '/mock/root', - bin: 'mainwpctl', - name: 'mainwpctl', + bin: 'mainwpcontrol', + name: 'mainwpcontrol', version: '1.0.0', - pjson: { name: 'mainwpctl', version: '1.0.0' }, + pjson: { name: 'mainwpcontrol', version: '1.0.0' }, dataDir: '/mock/data', cacheDir: '/mock/cache', configDir: '/mock/config', diff --git a/src/__tests__/e2e/login-abilities-flow.test.ts b/src/__tests__/e2e/login-abilities-flow.test.ts index e3d644a..709aad0 100644 --- a/src/__tests__/e2e/login-abilities-flow.test.ts +++ b/src/__tests__/e2e/login-abilities-flow.test.ts @@ -168,7 +168,7 @@ describe('E2E: Login → Abilities Flow', () => { await keychain.set('test-dashboard', password); expect(mockKeytarSetPassword).toHaveBeenCalledWith( - 'mainwpctl', + 'mainwpcontrol', 'test-dashboard', password ); @@ -192,7 +192,7 @@ describe('E2E: Login → Abilities Flow', () => { const retrieved = await keychain.get('test-dashboard'); - expect(mockKeytarGetPassword).toHaveBeenCalledWith('mainwpctl', 'test-dashboard'); + expect(mockKeytarGetPassword).toHaveBeenCalledWith('mainwpcontrol', 'test-dashboard'); expect(retrieved).toBe(password); }); }); diff --git a/src/__tests__/e2e/non-tty-behavior.test.ts b/src/__tests__/e2e/non-tty-behavior.test.ts index b87ddf7..320b22a 100644 --- a/src/__tests__/e2e/non-tty-behavior.test.ts +++ b/src/__tests__/e2e/non-tty-behavior.test.ts @@ -2,12 +2,12 @@ * E2E Test: Non-TTY Behavior * * Validates behavior in non-interactive (piped/CI) environments. - * Ensures mainwpctl doesn't hang in CI pipelines and provides + * Ensures mainwpcontrol doesn't hang in CI pipelines and provides * appropriate error messages for terminal-dependent features. * * INVARIANTS TESTED: - * - Bare `mainwpctl` in non-TTY exits with code 1 and guidance - * - `mainwpctl "message"` in non-TTY works (single-message mode) + * - Bare `mainwpcontrol` in non-TTY exits with code 1 and guidance + * - `mainwpcontrol "message"` in non-TTY works (single-message mode) * - --quiet suppresses stdout, exit code reflects success/failure * - --json output works in pipe * - Destructive --confirm without --force in non-TTY exits with error @@ -179,10 +179,10 @@ function createCommandInstance( const mockConfig = { root: '/mock/root', - bin: 'mainwpctl', - name: 'mainwpctl', + bin: 'mainwpcontrol', + name: 'mainwpcontrol', version: '1.0.0', - pjson: { name: 'mainwpctl', version: '1.0.0' }, + pjson: { name: 'mainwpcontrol', version: '1.0.0' }, dataDir: '/mock/data', cacheDir: '/mock/cache', configDir: '/mock/config', diff --git a/src/__tests__/process/abilities-info.test.ts b/src/__tests__/process/abilities-info.test.ts index e95f576..f8331e9 100644 --- a/src/__tests__/process/abilities-info.test.ts +++ b/src/__tests__/process/abilities-info.test.ts @@ -1,10 +1,10 @@ /** * Process-level tests for the `abilities info` command * - * Verifies that `mainwpctl abilities info ` correctly fetches and + * Verifies that `mainwpcontrol abilities info ` correctly fetches and * displays details for a specific ability. The command populates its cache * by calling listAbilities, then looks up the requested ability by name. - * Each test runs mainwpctl as a child process against a mock HTTP server. + * Each test runs mainwpcontrol as a child process against a mock HTTP server. */ import { describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from 'vitest'; diff --git a/src/__tests__/process/abilities-list.test.ts b/src/__tests__/process/abilities-list.test.ts index 89c937a..21c62a1 100644 --- a/src/__tests__/process/abilities-list.test.ts +++ b/src/__tests__/process/abilities-list.test.ts @@ -1,8 +1,8 @@ /** * Process-level tests for the `abilities list` command * - * Verifies that `mainwpctl abilities list` correctly fetches and displays - * abilities from the Dashboard API. Each test runs mainwpctl as a child + * Verifies that `mainwpcontrol abilities list` correctly fetches and displays + * abilities from the Dashboard API. Each test runs mainwpcontrol as a child * process against a mock HTTP server with an isolated config directory. */ diff --git a/src/__tests__/process/abilities-run.test.ts b/src/__tests__/process/abilities-run.test.ts index 7e61a19..f574666 100644 --- a/src/__tests__/process/abilities-run.test.ts +++ b/src/__tests__/process/abilities-run.test.ts @@ -1,5 +1,5 @@ /** - * Process-level tests for `mainwpctl abilities run` + * Process-level tests for `mainwpcontrol abilities run` * * Spawns the CLI as a child process against a mock HTTP server * to verify the full request/response lifecycle: input resolution, @@ -171,7 +171,7 @@ describe('abilities run', () => { }); // ------------------------------------------------------------------------- - // 4. echo '{"site_id": 5}' | mainwpctl abilities run get-site-v1 --input - --json + // 4. echo '{"site_id": 5}' | mainwpcontrol abilities run get-site-v1 --input - --json // ------------------------------------------------------------------------- describe('get-site-v1 --input - (stdin pipe)', () => { it('reads input from stdin and sends it as query params', async () => { diff --git a/src/__tests__/process/auth.test.ts b/src/__tests__/process/auth.test.ts index a3b1016..643e73e 100644 --- a/src/__tests__/process/auth.test.ts +++ b/src/__tests__/process/auth.test.ts @@ -1,7 +1,7 @@ /** * Process-level tests for the login command * - * Verifies authentication flow end-to-end by spawning mainwpctl as a child + * Verifies authentication flow end-to-end by spawning mainwpcontrol as a child * process against a mock HTTP server. Each test gets a fresh, empty config * directory to ensure isolation. */ diff --git a/src/__tests__/process/batch-wait.test.ts b/src/__tests__/process/batch-wait.test.ts index 5755ffb..f8aa889 100644 --- a/src/__tests__/process/batch-wait.test.ts +++ b/src/__tests__/process/batch-wait.test.ts @@ -2,7 +2,7 @@ * Process-level tests for batch job waiting * * Verifies --wait flag on `abilities run` and `jobs watch` by spawning - * mainwpctl as a child process against a mock HTTP server that returns + * mainwpcontrol as a child process against a mock HTTP server that returns * progressive batch job statuses. */ diff --git a/src/__tests__/process/doctor.test.ts b/src/__tests__/process/doctor.test.ts index 3ed7063..50bfb9e 100644 --- a/src/__tests__/process/doctor.test.ts +++ b/src/__tests__/process/doctor.test.ts @@ -1,7 +1,7 @@ /** * Process-level tests for the doctor command * - * Verifies diagnostic checks end-to-end by spawning mainwpctl as a child + * Verifies diagnostic checks end-to-end by spawning mainwpcontrol as a child * process against a mock HTTP server. Each test gets a fresh config * directory to ensure isolation. * diff --git a/src/__tests__/process/exit-codes.test.ts b/src/__tests__/process/exit-codes.test.ts index 2ae63d3..c25e7d6 100644 --- a/src/__tests__/process/exit-codes.test.ts +++ b/src/__tests__/process/exit-codes.test.ts @@ -1,7 +1,7 @@ /** * Process-level tests for the exit code contract * - * Verifies that mainwpctl exits with the correct code for each error category: + * Verifies that mainwpcontrol exits with the correct code for each error category: * 0 = Success * 1 = Input error * 2 = Auth / config error @@ -9,7 +9,7 @@ * 4 = API error * 5 = Internal error * - * Each test spawns mainwpctl as a real child process, so these validate + * Each test spawns mainwpcontrol as a real child process, so these validate * the full error-propagation path from command → base-command catch → exit. */ diff --git a/src/__tests__/process/fixtures/cli-runner.ts b/src/__tests__/process/fixtures/cli-runner.ts index a1708e5..5164508 100644 --- a/src/__tests__/process/fixtures/cli-runner.ts +++ b/src/__tests__/process/fixtures/cli-runner.ts @@ -58,7 +58,7 @@ export async function runCLI( MAINWP_ALLOW_HTTP: '1', // Skip native keytar — process tests run with isolated HOME where // macOS Keychain access is slow/unavailable. - MAINWPCTL_NO_KEYTAR: '1', + MAINWPCONTROL_NO_KEYTAR: '1', // Spread any extra env ...options.env, }; diff --git a/src/__tests__/process/fixtures/config-dir.ts b/src/__tests__/process/fixtures/config-dir.ts index 7aa5bec..152075e 100644 --- a/src/__tests__/process/fixtures/config-dir.ts +++ b/src/__tests__/process/fixtures/config-dir.ts @@ -25,15 +25,15 @@ export interface ConfigDirOptions { } export class ConfigDir { - /** The temp XDG_CONFIG_HOME path (parent of mainwpctl/). */ + /** The temp XDG_CONFIG_HOME path (parent of mainwpcontrol/). */ readonly xdgHome: string; - /** The mainwpctl config directory inside xdgHome. */ + /** The mainwpcontrol config directory inside xdgHome. */ readonly configPath: string; private constructor(xdgHome: string) { this.xdgHome = xdgHome; - this.configPath = join(xdgHome, 'mainwpctl'); + this.configPath = join(xdgHome, 'mainwpcontrol'); } /** @@ -43,7 +43,7 @@ export class ConfigDir { const xdgHome = await mkdtemp(join(tmpdir(), 'mwpctl-test-')); const instance = new ConfigDir(xdgHome); - // Create mainwpctl subdir + // Create mainwpcontrol subdir await mkdir(instance.configPath, { recursive: true }); // Write profiles.json diff --git a/src/__tests__/process/global-flags.test.ts b/src/__tests__/process/global-flags.test.ts index 54f8023..83f6bcb 100644 --- a/src/__tests__/process/global-flags.test.ts +++ b/src/__tests__/process/global-flags.test.ts @@ -2,7 +2,7 @@ * Process-Level Tests: Global Flags * * Validates cross-cutting CLI flags (--json, --quiet, --profile, --debug) - * and the defaultJsonOutput setting by spawning mainwpctl as a child + * and the defaultJsonOutput setting by spawning mainwpcontrol as a child * process against a mock HTTP server. Each test gets a fresh, isolated * config directory. */ diff --git a/src/__tests__/process/live-api.test.ts b/src/__tests__/process/live-api.test.ts index b99e0dc..b65b08d 100644 --- a/src/__tests__/process/live-api.test.ts +++ b/src/__tests__/process/live-api.test.ts @@ -1,5 +1,5 @@ /** - * Live Integration Tests for mainwpctl + * Live Integration Tests for mainwpcontrol * * Exercises the CLI against a real MainWP Dashboard (local testbed). * All destructive abilities use --dry-run only — never executes mutations. @@ -134,7 +134,7 @@ describe.skipIf(!dashboardOnline)('live integration tests', () => { it('smoke: --help exits 0', async () => { const r = await cli(['--help']); expect(r.exitCode).toBe(0); - expect(r.stdout).toContain('mainwpctl'); + expect(r.stdout).toContain('mainwpcontrol'); }); // ── Group 2: Login ────────────────────────────────────────────────────── diff --git a/src/__tests__/process/live-workflow-docs.test.ts b/src/__tests__/process/live-workflow-docs.test.ts index bce1fcf..23c5997 100644 --- a/src/__tests__/process/live-workflow-docs.test.ts +++ b/src/__tests__/process/live-workflow-docs.test.ts @@ -218,7 +218,7 @@ describe.skipIf(!dashboardOnline)('workflow documentation tests', () => { }); it('--input-file produces identical result to inline', async () => { - const tmpFile = join(tmpdir(), `mainwpctl-test-params-${Date.now()}.json`); + const tmpFile = join(tmpdir(), `mainwpcontrol-test-params-${Date.now()}.json`); writeFileSync(tmpFile, JSON.stringify({ site_id_or_domain: firstConnectedSiteId })); try { diff --git a/src/__tests__/process/scenarios.test.ts b/src/__tests__/process/scenarios.test.ts index 51dda24..8365233 100644 --- a/src/__tests__/process/scenarios.test.ts +++ b/src/__tests__/process/scenarios.test.ts @@ -1,7 +1,7 @@ /** * Process-level multi-step scenario tests * - * Tests realistic multi-command workflows by spawning mainwpctl as a child + * Tests realistic multi-command workflows by spawning mainwpcontrol as a child * process against a mock HTTP server. Each scenario simulates a real user * session: login, then run a sequence of abilities, verifying data flows * correctly between steps. diff --git a/src/__tests__/process/smoke.test.ts b/src/__tests__/process/smoke.test.ts index a559f37..12a027d 100644 --- a/src/__tests__/process/smoke.test.ts +++ b/src/__tests__/process/smoke.test.ts @@ -26,7 +26,7 @@ describe('smoke tests', () => { if (configWithoutProfile) await configWithoutProfile.cleanup(); }); - it('mainwpctl --help exits 0 and shows usage info', async () => { + it('mainwpcontrol --help exits 0 and shows usage info', async () => { // --help does not require a profile, so an empty config dir is fine configWithoutProfile = await ConfigDir.create({ profiles: [] }); @@ -39,11 +39,11 @@ describe('smoke tests', () => { const hasUsageInfo = /usage/i.test(combined) || /commands/i.test(combined) || - /mainwpctl/i.test(combined); + /mainwpcontrol/i.test(combined); expect(hasUsageInfo).toBe(true); }); - it('mainwpctl abilities --help exits 0', async () => { + it('mainwpcontrol abilities --help exits 0', async () => { configWithoutProfile = await ConfigDir.create({ profiles: [] }); const result = await runCLI(['abilities', '--help'], { @@ -53,7 +53,7 @@ describe('smoke tests', () => { expect(result.exitCode).toBe(0); }); - it('mainwpctl nonexistent exits non-zero with error on stderr', async () => { + it('mainwpcontrol nonexistent exits non-zero with error on stderr', async () => { configWithoutProfile = await ConfigDir.create({ profiles: [] }); const result = await runCLI(['nonexistent'], { @@ -64,7 +64,7 @@ describe('smoke tests', () => { expect(result.stderr.length).toBeGreaterThan(0); }); - it('bare mainwpctl in non-TTY shows help and exits 0', async () => { + it('bare mainwpcontrol in non-TTY shows help and exits 0', async () => { // When no command is provided, oclif shows the top-level help and exits 0 // (the default "chat" command is not invoked for bare invocation) configWithProfile = await ConfigDir.create({ @@ -91,7 +91,7 @@ describe('smoke tests', () => { expect(combined).toMatch(/commands/i); }); - it('bare mainwpctl in non-TTY without profile also shows help and exits 0', async () => { + it('bare mainwpcontrol in non-TTY without profile also shows help and exits 0', async () => { // Even without a profile, bare invocation shows help (no command runs) configWithoutProfile = await ConfigDir.create({ profiles: [] }); @@ -102,7 +102,7 @@ describe('smoke tests', () => { expect(result.exitCode).toBe(0); }); - it('mainwpctl "some message" exits 2 with command-not-found error', async () => { + it('mainwpcontrol "some message" exits 2 with command-not-found error', async () => { // oclif treats the argument as a command name lookup, not as a chat message arg. // Since there is no command called "some message", oclif exits with a command-not-found error. configWithProfile = await ConfigDir.create({ diff --git a/src/chat/chat-engine.test.ts b/src/chat/chat-engine.test.ts index e2e12f7..f0249f1 100644 --- a/src/chat/chat-engine.test.ts +++ b/src/chat/chat-engine.test.ts @@ -2061,7 +2061,7 @@ describe('ChatEngine', () => { const history = engine.getHistory(); expect(history[0]!.role).toBe('system'); - expect(history[0]!.content).toContain('mainwpctl'); + expect(history[0]!.content).toContain('mainwpcontrol'); }); it('should keep most recent N messages after truncation', async () => { diff --git a/src/chat/chat-engine.ts b/src/chat/chat-engine.ts index 0e41e23..5e56181 100644 --- a/src/chat/chat-engine.ts +++ b/src/chat/chat-engine.ts @@ -1,5 +1,5 @@ /** - * Chat Engine for mainwpctl + * Chat Engine for mainwpcontrol * * LLM interaction loop with safety enforcement. * diff --git a/src/chat/providers/anthropic.ts b/src/chat/providers/anthropic.ts index 842b551..f233bf2 100644 --- a/src/chat/providers/anthropic.ts +++ b/src/chat/providers/anthropic.ts @@ -1,5 +1,5 @@ /** - * Anthropic Provider for mainwpctl + * Anthropic Provider for mainwpcontrol * * Implements LLM provider interface for Claude models. */ diff --git a/src/chat/providers/gemini.ts b/src/chat/providers/gemini.ts index a20606c..1c14a62 100644 --- a/src/chat/providers/gemini.ts +++ b/src/chat/providers/gemini.ts @@ -1,5 +1,5 @@ /** - * Google Gemini Provider for mainwpctl + * Google Gemini Provider for mainwpcontrol * * Implements LLM provider interface for Gemini models. */ diff --git a/src/chat/providers/local.ts b/src/chat/providers/local.ts index 034b17f..eb177f9 100644 --- a/src/chat/providers/local.ts +++ b/src/chat/providers/local.ts @@ -1,5 +1,5 @@ /** - * Local LLM Provider for mainwpctl + * Local LLM Provider for mainwpcontrol * * Implements LLM provider interface for OpenAI-compatible local endpoints. * Supports llama.cpp, Ollama, LM Studio, and other OpenAI-compatible servers. diff --git a/src/chat/providers/openai.ts b/src/chat/providers/openai.ts index b77313e..a63309b 100644 --- a/src/chat/providers/openai.ts +++ b/src/chat/providers/openai.ts @@ -1,5 +1,5 @@ /** - * OpenAI Provider for mainwpctl + * OpenAI Provider for mainwpcontrol * * Implements LLM provider interface for OpenAI GPT models. */ diff --git a/src/chat/providers/openrouter.ts b/src/chat/providers/openrouter.ts index d1de4d7..2fa2f66 100644 --- a/src/chat/providers/openrouter.ts +++ b/src/chat/providers/openrouter.ts @@ -1,5 +1,5 @@ /** - * OpenRouter Provider for mainwpctl + * OpenRouter Provider for mainwpcontrol * * Implements LLM provider interface for OpenRouter. * OpenRouter provides access to multiple models through a unified API @@ -48,7 +48,7 @@ export class OpenRouterProvider extends OpenAICompatibleProvider { constructor(config: ProviderConfig) { super(config, { baseUrl: DEFAULT_BASE_URL, model: DEFAULT_MODEL }); - this.appName = 'mainwpctl'; + this.appName = 'mainwpcontrol'; } isConfigured(): boolean { diff --git a/src/chat/providers/provider.ts b/src/chat/providers/provider.ts index 20beea3..85141b9 100644 --- a/src/chat/providers/provider.ts +++ b/src/chat/providers/provider.ts @@ -1,5 +1,5 @@ /** - * LLM Provider Interface for mainwpctl + * LLM Provider Interface for mainwpcontrol * * Abstract interface for different LLM providers. * Supported: OpenAI, Anthropic, Gemini, OpenRouter, Local (OpenAI-compatible) diff --git a/src/chat/system-prompt.ts b/src/chat/system-prompt.ts index f89350e..017ad2e 100644 --- a/src/chat/system-prompt.ts +++ b/src/chat/system-prompt.ts @@ -13,7 +13,7 @@ import type { Ability } from '../core/abilities-executor.js'; * Core system prompt content * Derived from CHAT_PROMPT.md (authoritative document) */ -const CORE_PROMPT = `You are an AI assistant embedded in MainWP Control (\`mainwpctl\`), a command-line tool for MainWP Dashboard management. +const CORE_PROMPT = `You are an AI assistant embedded in MainWP Control (\`mainwpcontrol\`), a command-line tool for MainWP Dashboard management. ## Role diff --git a/src/chat/tool-envelope.ts b/src/chat/tool-envelope.ts index c5ef51c..843425f 100644 --- a/src/chat/tool-envelope.ts +++ b/src/chat/tool-envelope.ts @@ -1,5 +1,5 @@ /** - * Tool Envelope Parser for mainwpctl + * Tool Envelope Parser for mainwpcontrol * * Parses and validates LLM tool call responses. * Supports both native function calling (from provider) and JSON in content. diff --git a/src/commands/abilities/info.ts b/src/commands/abilities/info.ts index 4a26b17..e6bdf52 100644 --- a/src/commands/abilities/info.ts +++ b/src/commands/abilities/info.ts @@ -1,5 +1,5 @@ /** - * Abilities info command for mainwpctl + * Abilities info command for mainwpcontrol * * Shows detailed information about a specific ability. */ @@ -37,7 +37,7 @@ export default class AbilitiesInfo extends BaseCommand { if (!ability) { throw new InputError( - `Ability not found: ${args.name}. Run \`mainwpctl abilities list\` to see available abilities.` + `Ability not found: ${args.name}. Run \`mainwpcontrol abilities list\` to see available abilities.` ); } diff --git a/src/commands/abilities/list.ts b/src/commands/abilities/list.ts index 26df531..16ad54b 100644 --- a/src/commands/abilities/list.ts +++ b/src/commands/abilities/list.ts @@ -1,5 +1,5 @@ /** - * Abilities list command for mainwpctl + * Abilities list command for mainwpcontrol * * Lists all available abilities from the Dashboard. */ diff --git a/src/commands/abilities/run.ts b/src/commands/abilities/run.ts index 638d955..29098ed 100644 --- a/src/commands/abilities/run.ts +++ b/src/commands/abilities/run.ts @@ -1,5 +1,5 @@ /** - * Abilities run command for mainwpctl + * Abilities run command for mainwpcontrol * * Execute abilities with safety enforcement. * Routes through SafetyController for destructive actions. @@ -111,7 +111,7 @@ export default class AbilitiesRun extends BaseCommand { const ability = await executor.getAbility(args.name); if (!ability) { throw new InputError( - `Ability not found: ${args.name}. Run \`mainwpctl abilities list\` to see available abilities.` + `Ability not found: ${args.name}. Run \`mainwpcontrol abilities list\` to see available abilities.` ); } @@ -579,7 +579,7 @@ export default class AbilitiesRun extends BaseCommand { '', formatKeyValue('Job ID', jobId), '', - `Monitor progress with: mainwpctl jobs watch ${jobId}`, + `Monitor progress with: mainwpcontrol jobs watch ${jobId}`, ].join('\n'); } @@ -592,10 +592,10 @@ export default class AbilitiesRun extends BaseCommand { this.logToStderr(formatWarning(`"${abilityName}" is a destructive ability.`)); this.logToStderr(''); this.logToStderr('To preview changes:'); - this.logToStderr(` mainwpctl abilities run ${abilityName} --dry-run --input '{...}'`); + this.logToStderr(` mainwpcontrol abilities run ${abilityName} --dry-run --input '{...}'`); this.logToStderr(''); this.logToStderr('To execute after preview:'); - this.logToStderr(` mainwpctl abilities run ${abilityName} --confirm --input '{...}'`); + this.logToStderr(` mainwpcontrol abilities run ${abilityName} --confirm --input '{...}'`); this.logToStderr(''); } } diff --git a/src/commands/chat.ts b/src/commands/chat.ts index 56f2b28..e345b50 100644 --- a/src/commands/chat.ts +++ b/src/commands/chat.ts @@ -1,7 +1,7 @@ /** - * Default Chat Command for mainwpctl + * Default Chat Command for mainwpcontrol * - * Running `mainwpctl` without a subcommand enters interactive chat mode. + * Running `mainwpcontrol` without a subcommand enters interactive chat mode. * This is the primary interaction surface. * * INVARIANT: AI is the interaction surface, not the execution authority. @@ -159,8 +159,8 @@ export default class ChatCommand extends BaseCommand { // Non-interactive without a message: show help, exit if (!isInteractive() && !args.message) { this.logToStderr('Error: Interactive chat requires a terminal. Provide a message argument or use abilities run.'); - this.logToStderr(' mainwpctl "list all sites" # single message'); - this.logToStderr(' mainwpctl abilities run list-sites-v1 # direct command'); + this.logToStderr(' mainwpcontrol "list all sites" # single message'); + this.logToStderr(' mainwpcontrol abilities run list-sites-v1 # direct command'); this.exit(ExitCode.INPUT_ERROR); } diff --git a/src/commands/config/show.ts b/src/commands/config/show.ts index 42e6aca..9992293 100644 --- a/src/commands/config/show.ts +++ b/src/commands/config/show.ts @@ -1,5 +1,5 @@ /** - * Config Show Command for mainwpctl + * Config Show Command for mainwpcontrol * * Displays current configuration and settings. * @@ -286,7 +286,7 @@ export default class ConfigShowCommand extends BaseCommand { if (config.profile.credentialsSource === 'none') { this.log(` Credentials: ${color('✗ Not found', colors.red)}`); - this.log(` ${color('Run `mainwpctl login` or set MAINWP_APP_PASSWORD', colors.gray)}`); + this.log(` ${color('Run `mainwpcontrol login` or set MAINWP_APP_PASSWORD', colors.gray)}`); } else { const sourceLabel = config.profile.credentialsSource === 'keychain' @@ -298,7 +298,7 @@ export default class ConfigShowCommand extends BaseCommand { } } else { this.log(` ${color('No active profile configured', colors.yellow)}`); - this.log(` ${color('Run `mainwpctl login` or `mainwpctl profile use `', colors.gray)}`); + this.log(` ${color('Run `mainwpcontrol login` or `mainwpcontrol profile use `', colors.gray)}`); // Show available profiles count this.showAvailableProfilesHint(); diff --git a/src/commands/doctor.ts b/src/commands/doctor.ts index 911e1ec..239e534 100644 --- a/src/commands/doctor.ts +++ b/src/commands/doctor.ts @@ -1,5 +1,5 @@ /** - * Doctor Command for mainwpctl + * Doctor Command for mainwpcontrol * * Diagnoses configuration issues and validates connectivity. * @@ -127,7 +127,7 @@ export default class DoctorCommand extends BaseCommand { name: 'Profiles', status: 'fail', message: 'No profiles configured', - details: 'Run `mainwpctl login` to create a profile', + details: 'Run `mainwpcontrol login` to create a profile', }; } @@ -194,7 +194,7 @@ export default class DoctorCommand extends BaseCommand { name: 'Active Profile', status: 'fail', message: 'No active profile', - details: 'Run `mainwpctl login` or `mainwpctl profile use `', + details: 'Run `mainwpcontrol login` or `mainwpcontrol profile use `', }; } @@ -238,7 +238,7 @@ export default class DoctorCommand extends BaseCommand { status: 'fail', message: 'No credentials found', details: - 'Run `mainwpctl login` or set MAINWP_APP_PASSWORD environment variable', + 'Run `mainwpcontrol login` or set MAINWP_APP_PASSWORD environment variable', }; } diff --git a/src/commands/jobs/watch.ts b/src/commands/jobs/watch.ts index dd02722..336a232 100644 --- a/src/commands/jobs/watch.ts +++ b/src/commands/jobs/watch.ts @@ -1,5 +1,5 @@ /** - * Jobs watch command for mainwpctl + * Jobs watch command for mainwpcontrol * * Monitor batch job status with exponential backoff polling. * Streams progress updates until job completes or times out. diff --git a/src/commands/login.ts b/src/commands/login.ts index 0aaf2a2..a8f372e 100644 --- a/src/commands/login.ts +++ b/src/commands/login.ts @@ -1,5 +1,5 @@ /** - * Login command for mainwpctl + * Login command for mainwpcontrol * * Authenticates with a MainWP Dashboard and stores credentials. */ diff --git a/src/commands/profile/delete.ts b/src/commands/profile/delete.ts index 236032a..e3e44fd 100644 --- a/src/commands/profile/delete.ts +++ b/src/commands/profile/delete.ts @@ -1,5 +1,5 @@ /** - * Profile delete command for mainwpctl + * Profile delete command for mainwpcontrol * * Deletes a Dashboard profile and its credentials. */ @@ -45,7 +45,7 @@ export default class ProfileDelete extends BaseCommand { if (!profile) { throw new ConfigError( - `Profile not found: ${args.name}. Run \`mainwpctl profile list\` to see available profiles.` + `Profile not found: ${args.name}. Run \`mainwpcontrol profile list\` to see available profiles.` ); } diff --git a/src/commands/profile/list.ts b/src/commands/profile/list.ts index cc6b16c..12c1c4e 100644 --- a/src/commands/profile/list.ts +++ b/src/commands/profile/list.ts @@ -1,5 +1,5 @@ /** - * Profile list command for mainwpctl + * Profile list command for mainwpcontrol * * Lists all saved Dashboard profiles. */ @@ -45,7 +45,7 @@ export default class ProfileList extends BaseCommand { }, () => { if (profiles.length === 0) { - return 'No profiles configured. Run `mainwpctl login` to add one.'; + return 'No profiles configured. Run `mainwpcontrol login` to add one.'; } const lines = [formatHeading('Profiles'), '']; diff --git a/src/commands/profile/use.ts b/src/commands/profile/use.ts index b554b5f..e3c8be3 100644 --- a/src/commands/profile/use.ts +++ b/src/commands/profile/use.ts @@ -1,5 +1,5 @@ /** - * Profile use command for mainwpctl + * Profile use command for mainwpcontrol * * Switches the active Dashboard profile. */ @@ -43,7 +43,7 @@ export default class ProfileUse extends BaseCommand { if (!profile) { throw new ConfigError( - `Profile not found: ${args.name}. Run \`mainwpctl profile list\` to see available profiles.` + `Profile not found: ${args.name}. Run \`mainwpcontrol profile list\` to see available profiles.` ); } diff --git a/src/config/keychain.ts b/src/config/keychain.ts index 214f6af..7885105 100644 --- a/src/config/keychain.ts +++ b/src/config/keychain.ts @@ -1,5 +1,5 @@ /** - * Keychain integration for mainwpctl + * Keychain integration for mainwpcontrol * * Secure credential storage with environment variable fallback. * @@ -14,7 +14,7 @@ import { AuthError } from '../utils/errors.js'; /** * Service name for keychain entries */ -const SERVICE_NAME = 'mainwpctl'; +const SERVICE_NAME = 'mainwpcontrol'; /** * Environment variable for fallback @@ -60,7 +60,7 @@ async function loadKeytar(): Promise { } // Allow explicit opt-out for CI/containers where native keychain is unavailable - if (process.env['MAINWPCTL_NO_KEYTAR'] === '1') { + if (process.env['MAINWPCONTROL_NO_KEYTAR'] === '1') { keytarAvailable = false; return null; } @@ -194,7 +194,7 @@ export class Keychain { throw new AuthError( `No credentials found for profile "${profileName}".`, undefined, - `Run \`mainwpctl login\` or set ${ENV_VAR} environment variable` + `Run \`mainwpcontrol login\` or set ${ENV_VAR} environment variable` ); } diff --git a/src/config/profile-store.ts b/src/config/profile-store.ts index 7a9185d..3457d83 100644 --- a/src/config/profile-store.ts +++ b/src/config/profile-store.ts @@ -1,5 +1,5 @@ /** - * Profile store for mainwpctl + * Profile store for mainwpcontrol * * Manages multiple Dashboard connection profiles. */ @@ -64,7 +64,7 @@ async function loadProfilesFile(): Promise { throw new ConfigError( `Failed to load profiles: ${(error as Error).message}`, undefined, - 'Check file permissions for ~/.config/mainwpctl/profiles.json' + 'Check file permissions for ~/.config/mainwpcontrol/profiles.json' ); } } @@ -115,7 +115,7 @@ export class ProfileStore { * Validate a profile's required fields and URL format */ private validateProfile(profile: Profile): void { - const validationHint = 'Run `mainwpctl login` to create a valid profile'; + const validationHint = 'Run `mainwpcontrol login` to create a valid profile'; if (!profile.name || profile.name.trim().length === 0) { throw new ConfigError( @@ -232,7 +232,7 @@ export class ProfileStore { throw new ConfigError( `Profile not found: ${name}`, undefined, - 'List available profiles with `mainwpctl profile list`' + 'List available profiles with `mainwpcontrol profile list`' ); } @@ -290,7 +290,7 @@ export class ProfileStore { throw new ConfigError( `Profile not found: ${name}`, undefined, - 'List available profiles with `mainwpctl profile list`' + 'List available profiles with `mainwpcontrol profile list`' ); } diff --git a/src/config/settings.ts b/src/config/settings.ts index 47efe1f..89cc8f9 100644 --- a/src/config/settings.ts +++ b/src/config/settings.ts @@ -1,5 +1,5 @@ /** - * Settings file support for mainwpctl + * Settings file support for mainwpcontrol */ import { promises as fs } from 'node:fs'; @@ -72,9 +72,9 @@ export const SETTINGS_DEFAULTS: ResolvedSettings = { export function getConfigDir(): string { const xdgConfig = process.env['XDG_CONFIG_HOME']; if (xdgConfig) { - return join(xdgConfig, 'mainwpctl'); + return join(xdgConfig, 'mainwpcontrol'); } - return join(homedir(), '.config', 'mainwpctl'); + return join(homedir(), '.config', 'mainwpcontrol'); } /** @@ -86,7 +86,7 @@ export function getSettingsPath(): string { /** * Cached settings (cleared on explicit reload). - * No TTL needed: mainwpctl is a short-lived CLI process — settings are read + * No TTL needed: mainwpcontrol is a short-lived CLI process — settings are read * once per invocation. clearSettingsCache() handles explicit invalidation * (e.g. after saveSettings). */ diff --git a/src/core/abilities-executor.ts b/src/core/abilities-executor.ts index 236c8ff..d801119 100644 --- a/src/core/abilities-executor.ts +++ b/src/core/abilities-executor.ts @@ -1,5 +1,5 @@ /** - * Abilities Executor for mainwpctl + * Abilities Executor for mainwpcontrol * * Single execution pathway for all ability calls. * INVARIANT: Both commands and chat route through this module. @@ -118,7 +118,7 @@ export class AbilitiesExecutor { throw new InputError( `Unknown ability: ${abilityName}`, undefined, - 'List available abilities with `mainwpctl abilities list`' + 'List available abilities with `mainwpcontrol abilities list`' ); } diff --git a/src/core/batch-manager.ts b/src/core/batch-manager.ts index b05a575..d7882bc 100644 --- a/src/core/batch-manager.ts +++ b/src/core/batch-manager.ts @@ -1,5 +1,5 @@ /** - * Batch Manager for mainwpctl + * Batch Manager for mainwpcontrol * * Handles batch operations with polling and resume capabilities. * Provides exponential backoff for job status polling. diff --git a/src/core/http-client.ts b/src/core/http-client.ts index 5ece8bd..93d045a 100644 --- a/src/core/http-client.ts +++ b/src/core/http-client.ts @@ -1,5 +1,5 @@ /** - * HTTP Client for mainwpctl + * HTTP Client for mainwpcontrol * * Single abstraction for all API traffic. * INVARIANT: All HTTP requests MUST go through this module. @@ -340,7 +340,7 @@ export class HttpClient { Authorization: this.authHeader, 'Content-Type': 'application/json', Accept: 'application/json', - 'User-Agent': `mainwpctl/${PKG_VERSION}`, + 'User-Agent': `mainwpcontrol/${PKG_VERSION}`, ...custom, }; } @@ -357,7 +357,7 @@ export class HttpClient { throw new AuthError( 'Authentication failed. Check your credentials.', sanitizedData, - 'Run `mainwpctl login` to update your credentials' + 'Run `mainwpcontrol login` to update your credentials' ); case 403: throw new AuthError( @@ -403,7 +403,7 @@ export class HttpClient { ENOTFOUND: () => new NetworkError( 'Host not found. Check the Dashboard URL.', undefined, - 'Check the Dashboard URL in your profile with `mainwpctl config show`' + 'Check the Dashboard URL in your profile with `mainwpcontrol config show`' ), CERT_HAS_EXPIRED: () => new TLSError( 'SSL certificate error. Use --skip-ssl-verify if needed.', diff --git a/src/core/safety-controller.ts b/src/core/safety-controller.ts index 547056c..804aeb5 100644 --- a/src/core/safety-controller.ts +++ b/src/core/safety-controller.ts @@ -1,5 +1,5 @@ /** - * Safety Controller for mainwpctl + * Safety Controller for mainwpcontrol * * Enforces the destructive action protocol defined in PLAN.md: * - Safety check happens BEFORE any network call diff --git a/src/lib/base-command.ts b/src/lib/base-command.ts index 6a5e7df..fc9373c 100644 --- a/src/lib/base-command.ts +++ b/src/lib/base-command.ts @@ -1,5 +1,5 @@ /** - * Base command for mainwpctl + * Base command for mainwpcontrol * * Provides common functionality for all CLI commands: * - Profile and authentication management @@ -54,7 +54,7 @@ type CommonFlags = Interfaces.InferredFlags; /** * Base command class * - * All mainwpctl commands should extend this class. + * All mainwpcontrol commands should extend this class. */ export abstract class BaseCommand extends Command { /** @@ -157,7 +157,7 @@ export abstract class BaseCommand extends Command { throw new ConfigError( `Profile not found: ${profileName}`, undefined, - 'List available profiles with `mainwpctl profile list` or create one with `mainwpctl login`' + 'List available profiles with `mainwpcontrol profile list` or create one with `mainwpcontrol login`' ); } this.currentProfile = profile; @@ -167,7 +167,7 @@ export abstract class BaseCommand extends Command { throw new ConfigError( 'No profile configured.', undefined, - 'Create your first profile with `mainwpctl login`' + 'Create your first profile with `mainwpcontrol login`' ); } } diff --git a/src/output/formatter.ts b/src/output/formatter.ts index 0163e6c..9cd8db0 100644 --- a/src/output/formatter.ts +++ b/src/output/formatter.ts @@ -1,5 +1,5 @@ /** - * Human-readable output formatter for mainwpctl + * Human-readable output formatter for mainwpcontrol */ import { isMainWPCTLError } from '../utils/errors.js'; diff --git a/src/output/json-envelope.ts b/src/output/json-envelope.ts index f43c94e..162d837 100644 --- a/src/output/json-envelope.ts +++ b/src/output/json-envelope.ts @@ -1,5 +1,5 @@ /** - * JSON output envelope for mainwpctl + * JSON output envelope for mainwpcontrol * * This structure is stable and should not be changed without a major version bump. */ diff --git a/src/utils/audit-logger.ts b/src/utils/audit-logger.ts index ec76cdc..46940cb 100644 --- a/src/utils/audit-logger.ts +++ b/src/utils/audit-logger.ts @@ -1,9 +1,9 @@ /** - * Audit Logger for mainwpctl + * Audit Logger for mainwpcontrol * * Logs all destructive actions with preview, user decision, and execution result. * - * Log location: ~/.config/mainwpctl/audit.log + * Log location: ~/.config/mainwpcontrol/audit.log * Format: Newline-delimited JSON (NDJSON) * Rotation: When file exceeds 10MB, rotates to audit.log.1, audit.log.2, etc. * Retention: Keeps last 5 rotated files diff --git a/src/utils/colors.ts b/src/utils/colors.ts index 89a839f..7429119 100644 --- a/src/utils/colors.ts +++ b/src/utils/colors.ts @@ -1,5 +1,5 @@ /** - * Shared color utilities for mainwpctl + * Shared color utilities for mainwpcontrol * * Respects NO_COLOR env var and non-TTY detection. * All terminal coloring should go through these functions. diff --git a/src/utils/errors.ts b/src/utils/errors.ts index 6b87547..b838a37 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -1,5 +1,5 @@ /** - * Error classes for mainwpctl + * Error classes for mainwpcontrol * * Each error class maps to a specific exit code. */ @@ -7,7 +7,7 @@ import { ExitCode, type ExitCodeValue } from './exit-codes.js'; /** - * Base error class for mainwpctl errors + * Base error class for mainwpcontrol errors */ export abstract class MainWPCTLError extends Error { abstract readonly exitCode: ExitCodeValue; diff --git a/src/utils/exit-codes.ts b/src/utils/exit-codes.ts index 540882d..70fa8cf 100644 --- a/src/utils/exit-codes.ts +++ b/src/utils/exit-codes.ts @@ -1,5 +1,5 @@ /** - * Exit codes for mainwpctl + * Exit codes for mainwpcontrol * * These codes are stable and documented. Do not change without updating docs. */ diff --git a/src/utils/format.ts b/src/utils/format.ts index e6e2579..61720cf 100644 --- a/src/utils/format.ts +++ b/src/utils/format.ts @@ -1,5 +1,5 @@ /** - * Formatting utilities for mainwpctl + * Formatting utilities for mainwpcontrol * * Provides consistent secret masking across all commands. */ diff --git a/src/utils/prompt.ts b/src/utils/prompt.ts index d1b2608..46048c7 100644 --- a/src/utils/prompt.ts +++ b/src/utils/prompt.ts @@ -1,5 +1,5 @@ /** - * Interactive prompting utilities for mainwpctl + * Interactive prompting utilities for mainwpcontrol * * Handles user confirmation for destructive actions. * Auto-declines in non-interactive mode unless explicit flags are used. diff --git a/src/utils/retry.ts b/src/utils/retry.ts index 417753c..b89c9be 100644 --- a/src/utils/retry.ts +++ b/src/utils/retry.ts @@ -1,5 +1,5 @@ /** - * Retry utilities for mainwpctl + * Retry utilities for mainwpcontrol * * Provides exponential backoff functionality for polling operations. */ diff --git a/src/utils/terminal-sanitizer.ts b/src/utils/terminal-sanitizer.ts index 8168af2..ed1395e 100644 --- a/src/utils/terminal-sanitizer.ts +++ b/src/utils/terminal-sanitizer.ts @@ -1,5 +1,5 @@ /** - * Terminal Output Sanitizer for mainwpctl + * Terminal Output Sanitizer for mainwpcontrol * * Security utility to strip ANSI escape sequences and control characters * from untrusted data before rendering to terminal output. diff --git a/src/validation/input-sanitizer.ts b/src/validation/input-sanitizer.ts index 70aeb3a..0e42be6 100644 --- a/src/validation/input-sanitizer.ts +++ b/src/validation/input-sanitizer.ts @@ -1,5 +1,5 @@ /** - * Input Sanitizer for mainwpctl + * Input Sanitizer for mainwpcontrol * * Security sanitization for inputs: * - Input limits (string length, array elements, object depth) @@ -60,7 +60,7 @@ const PATH_PATTERNS = [ /\/home\/[^/\s]+/g, /C:\\Users\\[^\\]+/gi, // Config directories - /\.config\/mainwpctl/g, + /\.config\/mainwpcontrol/g, ]; /** diff --git a/src/validation/schema-validator.ts b/src/validation/schema-validator.ts index 4f04c6e..757632c 100644 --- a/src/validation/schema-validator.ts +++ b/src/validation/schema-validator.ts @@ -1,5 +1,5 @@ /** - * Schema Validator for mainwpctl + * Schema Validator for mainwpcontrol * * AJV-based input validation against ability JSON schemas. * Caches compiled schemas for performance. @@ -97,7 +97,7 @@ export class SchemaValidator { throw new SchemaValidationError( `Invalid input for ability "${abilityName}": ${errorMessages}`, result.errors, - `Check the ability schema with \`mainwpctl abilities info ${abilityName}\` for required fields and types` + `Check the ability schema with \`mainwpcontrol abilities info ${abilityName}\` for required fields and types` ); } From 01edfa2113cb0bfd8fb3e905b9ff9c09f35c9457 Mon Sep 17 00:00:00 2001 From: Dennis Dornon Date: Tue, 24 Mar 2026 10:19:57 -0400 Subject: [PATCH 2/2] fix stale doc references missed by bulk rename - .env.example: config dir comment still said ~/.config/mainwpctl - README.md: 3 references to MAINWPCTL_NO_KEYTAR (runtime uses MAINWPCONTROL_NO_KEYTAR) - docs/workflows/*.md: version output said mainwpcontrol/x.y.z but CLI prints @mainwp/control/x.y.z (oclif uses npm package name) --- .env.example | 2 +- README.md | 6 +++--- docs/workflows/daily-health-check.md | 4 ++-- docs/workflows/input-from-file.md | 4 ++-- docs/workflows/monitoring-integration.md | 4 ++-- docs/workflows/monthly-batch-updates.md | 4 ++-- docs/workflows/plugin-deployment-verification.md | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.env.example b/.env.example index 6060fc0..dfeeccf 100644 --- a/.env.example +++ b/.env.example @@ -40,5 +40,5 @@ # DEBUG=1 # ─── Paths ─────────────────────────────────────────────────────────── -# Override config directory (default: ~/.config/mainwpctl) +# Override config directory (default: ~/.config/mainwpcontrol) # XDG_CONFIG_HOME= diff --git a/README.md b/README.md index 5b62a76..c126ec2 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ mainwpcontrol login --url https://dashboard.example.com --username admin mainwpcontrol abilities run list-sites-v1 --json ``` -> **Tip:** If keytar is installed but broken, set `MAINWPCTL_NO_KEYTAR=1` to skip loading it entirely. +> **Tip:** If keytar is installed but broken, set `MAINWPCONTROL_NO_KEYTAR=1` to skip loading it entirely. When the OS keychain is unavailable, `mainwpcontrol` does not persist plaintext credentials. Keep `MAINWP_APP_PASSWORD` set for each run on CI, cron hosts, and headless servers. @@ -284,7 +284,7 @@ In CI/scripted workflows, you can pass `--confirm --force` directly if you've al | Variable | Description | |----------|-------------| | `MAINWP_APP_PASSWORD` | Application password for non-interactive login and commands when keychain storage is unavailable | -| `MAINWPCTL_NO_KEYTAR` | Set to `1` to skip keytar (keychain) loading entirely | +| `MAINWPCONTROL_NO_KEYTAR` | Set to `1` to skip keytar (keychain) loading entirely | | `MAINWP_ALLOW_HTTP` | Set to `1` to allow insecure HTTP Dashboard URLs | ### Chat Configuration (optional) @@ -360,7 +360,7 @@ Keytar requires native C++ compilation on some platforms. If it fails: export MAINWP_APP_PASSWORD='your-application-password' mainwpcontrol login --url https://dashboard.example.com --username admin ``` -2. **Or skip keytar explicitly** by setting `MAINWPCTL_NO_KEYTAR=1` before running commands. +2. **Or skip keytar explicitly** by setting `MAINWPCONTROL_NO_KEYTAR=1` before running commands. The pre-built binaries cover macOS, Windows, and Linux (x64/arm64). If you're on a different platform or architecture, you'll need C++ build tools (`gcc`, `g++`, `make`) or the env var approach. diff --git a/docs/workflows/daily-health-check.md b/docs/workflows/daily-health-check.md index 758d01e..65e3b6f 100644 --- a/docs/workflows/daily-health-check.md +++ b/docs/workflows/daily-health-check.md @@ -91,10 +91,10 @@ mainwpcontrol --version Expected output: ``` -mainwpcontrol/x.y.z darwin-arm64 node-vNN.NN.N +@mainwp/control/x.y.z darwin-arm64 node-vNN.NN.N ``` -You should see `mainwpcontrol/` followed by version information. The exact values depend on your system and Node.js version. +You should see `@mainwp/control/` followed by version information. The exact values depend on your system and Node.js version. --- diff --git a/docs/workflows/input-from-file.md b/docs/workflows/input-from-file.md index 1c2ffd0..8f203ce 100644 --- a/docs/workflows/input-from-file.md +++ b/docs/workflows/input-from-file.md @@ -106,10 +106,10 @@ mainwpcontrol --version Expected output: ``` -mainwpcontrol/x.y.z +@mainwp/control/x.y.z ``` -You should see `mainwpcontrol/` followed by a version number. The exact values depend on your system. +You should see `@mainwp/control/` followed by a version number. The exact values depend on your system. --- diff --git a/docs/workflows/monitoring-integration.md b/docs/workflows/monitoring-integration.md index 7c27f09..03346a2 100644 --- a/docs/workflows/monitoring-integration.md +++ b/docs/workflows/monitoring-integration.md @@ -82,10 +82,10 @@ mainwpcontrol --version Expected output: ``` -mainwpcontrol/x.y.z darwin-arm64 node-vNN.NN.N +@mainwp/control/x.y.z darwin-arm64 node-vNN.NN.N ``` -You should see `mainwpcontrol/` followed by a version number. The exact values depend on your system. +You should see `@mainwp/control/` followed by a version number. The exact values depend on your system. --- diff --git a/docs/workflows/monthly-batch-updates.md b/docs/workflows/monthly-batch-updates.md index 34f829a..a86c108 100644 --- a/docs/workflows/monthly-batch-updates.md +++ b/docs/workflows/monthly-batch-updates.md @@ -79,10 +79,10 @@ mainwpcontrol --version Expected output: ``` -mainwpcontrol/x.y.z +@mainwp/control/x.y.z ``` -You should see `mainwpcontrol/` followed by a version number. As long as the output starts with `mainwpcontrol/`, the installation is working. +You should see `@mainwp/control/` followed by a version number. As long as the output starts with `@mainwp/control/`, the installation is working. If you see `command not found`, make sure Node.js 20+ is installed and that your system PATH includes the npm global bin directory. Run `npm config get prefix` to find where npm installs global packages. diff --git a/docs/workflows/plugin-deployment-verification.md b/docs/workflows/plugin-deployment-verification.md index 1f44996..9f08a9b 100644 --- a/docs/workflows/plugin-deployment-verification.md +++ b/docs/workflows/plugin-deployment-verification.md @@ -86,10 +86,10 @@ mainwpcontrol --version Expected output: ``` -mainwpcontrol/x.y.z darwin-arm64 node-vNN.NN.N +@mainwp/control/x.y.z darwin-arm64 node-vNN.NN.N ``` -You should see `mainwpcontrol/` followed by a version number. If you see `command not found`, make sure Node.js 20+ is installed and try opening a new terminal window. +You should see `@mainwp/control/` followed by a version number. If you see `command not found`, make sure Node.js 20+ is installed and try opening a new terminal window. ---