Skip to content

The command line

The vroxy CLI does from a terminal what you’d otherwise do in the workspace: read a room, post to it, edit the knowledge base, manage seats, and configure custom bot tools. Python 3.9 or newer, and no dependencies at all — it uses only the standard library, so it runs on a box that has nothing but python3.

Terminal window
curl -fsSL https://raw.githubusercontent.com/VroxyAI/vroxy/main/install.sh | bash

That installs the vroxy command and then asks whether this machine should also run a dispatch agent. Answer no and nothing privileged happens — the CLI lands in ~/.local/bin and that is the end of it. --cli skips the question entirely:

Terminal window
curl -fsSL https://raw.githubusercontent.com/VroxyAI/vroxy/main/install.sh | bash -s -- --cli

If you would rather read the script first — a reasonable instinct with anything piped into a shell — clone it and run the same file:

Terminal window
git clone https://github.com/VroxyAI/vroxy.git && cd vroxy && ./install.sh --cli

The installer uses pipx when you have it, pip install --user when you don’t, and falls back to a virtualenv of its own when the system Python refuses user installs, which most current Linux distributions now do. All three routes end with vroxy on your PATH.

Terminal window
vroxy login # prompts; token saved 0600
vroxy workspaces
vroxy rooms <workspace>
vroxy read <workspace> <room> --limit 50
vroxy post <workspace> <room> "shipped 2.148.0"
vroxy dispatch <workspace> # is the agent up

Every command takes --json, which is the point of it existing: an agent working in a checkout can answer questions about live workspace state instead of asking a person to copy-paste.

This is the difference between the CLI and the REST API, and it decides which one you want.

An API token belongs to the workspace. It is an application credential: it does whatever its scopes allow, and it is not a person.

The CLI signs in as you. Every call resolves the workspace through your own membership and is checked against your own capabilities, so the CLI can do exactly what you could do in the web app — no more. If you hold docs.read but not docs.write, vroxy docs … publish refuses, the same way the button would be missing. Revoking access is removing the seat; there is no separate CLI permission to remember.

That also means a workspace you hold no seat in returns not found, never “forbidden” — the same rule the rest of the product follows. It won’t confirm that a workspace exists somewhere you can’t see it.

Terminal window
vroxy docs <ws> list --status draft
vroxy docs <ws> list --q refund
vroxy docs <ws> show <doc>
vroxy docs <ws> create "Refund policy" --file refunds.md
cat refunds.md | vroxy docs <ws> edit <doc> --body -
vroxy docs <ws> publish <doc>
vroxy docs <ws> unpublish <doc>
vroxy docs <ws> delete <doc>

--body - reads standard input, so a doc can come out of a pipe, a heredoc, or a file in your repository. A doc is created as a draft and stays invisible to the bot until you publish it — see Knowledge base.

Reading needs docs.read; everything else needs docs.write.

Terminal window
vroxy members <ws> list
vroxy members <ws> invite sam@example.com admin
vroxy members <ws> role 42 operator
vroxy members <ws> remove 42
vroxy members <ws> revoke <invitation>

list prints each seat’s membership id — the number role and remove take — alongside any pending invitations and their hashids.

Two rules are enforced on the server, not by the CLI, and they are the same two the workspace UI enforces: you cannot grant a level above your own, and you cannot act on someone at or above your own. An admin can promote an operator and cannot touch another admin. The owner’s seat can be neither demoted nor removed by anybody, including the owner — transfer ownership first.

Removing yourself is the exception that needs no capability: leaving is not managing members, and nobody needs permission to walk out.

Terminal window
vroxy tools <ws> list
vroxy tools <ws> show <tool>
vroxy tools <ws> create search_listings \
--label "Search listings" \
--description "Search listings by keyword and location." \
--url "https://example.com/search?q={query}&location={location}" \
--param "query=what to search for" \
--param "location=city or region, optional" \
--kind link --access public
vroxy tools <ws> disable <tool>
vroxy tools <ws> enable <tool>
vroxy tools <ws> delete <tool>

Each --param is name=description, repeated once per placeholder in the URL template. The description is not decoration — it is what the model reads to decide what to put there, which is why the CLI takes them as flags rather than making you hand-write a JSON array.

--kind fetch makes the server retrieve the built URL and summarize it rather than just sharing the link, and --access gates the tool on the visitor’s verified level. Both are explained in Custom bot tools; the CLI is a different way to set the same fields, with the same guard rails.

Reading needs tools.read, changing needs tools.write, and creating a tool also needs custom_tools on your plan.

~/.config/vroxy/credentials.json, mode 0600, set before the token is written rather than after — a token written first and restricted second is world-readable for the gap in between.

Your password is never a command-line argument. argv is readable through /proc and lands in shell history, so login prompts for it, or reads VROXY_PASSWORD from the environment for CI.

A token saved for one host is never sent to another. Overrides: VROXY_HOST, VROXY_TOKEN, VROXY_CONFIG_DIR.

Terminal window
vroxy logout # forget the saved token