A CLI to run a self-hosted Dograh voice-agent platform from the terminal: agents, calls, transcripts, numbers, models, campaigns, tools, keys, and an MCP server that exposes all of it to an agent. No dashboard clicking.
Dograh ships a REST API, generated SDKs, a dashboard, and an MCP server for building agents. It does not ship a command line for running them. Everything you do to operate a voice agent in production (which number routes where, what the last call cost, flip a model, place a test call, read the transcript) means clicking through the UI. dograh-ctl is the missing operations surface: scriptable (--json everywhere), diffable, and automatable, and dograh-ctl serve hands the same verbs to an agent over MCP.
From PyPI:
uv tool install dograh-ctl # or: pip install dograh-ctl
uvx dograh-ctl --help # try it without installingOr straight from GitHub:
uv tool install git+https://github.com/erickcxc/dograh-ctlFrom a clone: pip install -e . (or uv sync). Python 3.10+.
Point it at your instance and key (create a key in Dograh, under Developers):
export DOGRAH_BASE_URL=https://your-dograh-host
export DOGRAH_API_KEY=dgr_xxx
dograh-ctl pingAuth is the X-API-Key header. The key is read from the environment and stays in .env (gitignored), never in the repo, never in this tool's output.
dograh-ctl agents list # what agents exist
dograh-ctl agents get 7 # graph summary + model override (masked)
dograh-ctl runs chat 7 -m "hello" # talk to an agent, no telephony
dograh-ctl models set --realtime google_realtime/gemini-3.1-flash-live-preview
dograh-ctl agents publish 7 # edits are drafts until published
dograh-ctl runs trigger 7 --to +13135550100 --yes # place a real call
dograh-ctl runs transcript 501 # read it back
dograh-ctl runs latency --json | jq .p95 # everything is scriptableEvery command accepts --json (raw API payload, for scripts). Every failure is one line on stderr with an exit code: 2 for local configuration problems, 1 for anything the instance refused or could not be reached for. No tracebacks.
| Group | Command | What it does |
|---|---|---|
ping |
Verify connectivity and API-key auth. | |
| agents | list |
List voice agents (workflows). |
get <id> |
Name, status, version, node summary, model override (secrets masked). | |
create -u USE_CASE -d DESCRIPTION [--call-type] |
Generate an agent from a use case. | |
set-prompt <id> PROMPT |
Replace the prompt on every agentNode (saves a draft). | |
rename <id> NAME |
Rename. | |
set-model <id> --realtime P/M / --llm P/M |
Per-agent model override, read-modify-write (saves a draft). | |
publish <id> |
Promote the draft. Production inbound calls use the published version. | |
validate <id> |
Validate the draft graph. | |
| runs | list [-n 100] |
Recent call runs: duration, disposition, model. |
latency [-n 100] |
avg/p50/p95/min/max call duration. | |
trigger <agent> --to +E164 [--config ID] [--from-id ID] --yes |
Place an outbound call; resolves the run id. | |
transcript <run> [--agent ID] |
Print the transcript. | |
recording <run> [--out FILE] [--track ...] |
Download the recording. | |
chat <agent> [-m TEXT] |
Text session with an agent (no telephony). | |
| numbers | list |
Numbers and which agent each routes to. |
assign +E164 <agent> |
Route a number to an agent. | |
add +E164 [--agent ID] [--label] [--config ID] |
Register a number you already own. | |
remove +E164 --yes |
Remove from Dograh (does not release it at the carrier). | |
| models | show |
Org model configuration: mode, realtime, llm, tts, stt. |
set --realtime P/M / --llm P/M / --tts P/M / --stt P/M |
Change one block; the server re-merges your stored secrets. | |
| campaigns | list, status <id>, watch <id> [--interval] [--once] |
Campaigns, live progress, and a live dashboard while a campaign dials (numbers masked to the last 4 digits). |
create --name N --agent ID --csv FILE [--config ID] [--max-concurrency N] |
Upload a CSV (phone_number column, see examples/campaign-sample.csv) and create. |
|
start <id> --yes, pause <id> |
Control. start places real calls. |
|
| telephony | configs, providers |
Telephony configurations; supported providers and their fields. |
| tools | list [--status] [--category] |
Tools agents can call (HTTP, MCP, transfer, ...). |
| keys | list [--all], create NAME [--reveal], revoke <id> --yes |
Org API keys. create prints the prefix only unless --reveal. |
| serve | serve |
MCP server (stdio) exposing the operations verbs above. |
Buying a number is a carrier action: twilio phone-numbers:buy:local --country-code US --area-code 313, then dograh-ctl numbers add +1313... --agent 7.
- Verbs that place calls or cost money (
runs trigger,campaigns start,numbers remove,keys revoke) ask for confirmation; pass--yesin scripts. models setandagents set-modelread the current configuration, change one block, and write the whole thing back, so masked secrets are merged by the server, never overwritten with a placeholder.- Nothing prints a secret.
keys createshows the prefix;--revealprints the full key once. - Edits to an agent are drafts.
agents publishis the step that changes production behaviour.
This is the reason dograh-ctl exists: a coding agent should be able to create a voice agent, publish it, give it a number, test it, call it, and read the transcript, without a human clicking through a dashboard.
-
One-step install for Claude Code (MCP server + skill + setup command):
claude plugin marketplace add erickcxc/dograh-ctl claude plugin install dograh-ctl
The plugin registers
dograh-ops(uvx dograh-ctl serve, credentials passed through from your shell as${DOGRAH_BASE_URL}/${DOGRAH_API_KEY}, never stored) and installs thedograh-ctlskill, which teaches the lifecycle: create -> set_prompt -> set_model -> validate -> publish -> number -> chat test -> call -> transcript./dograh-ctl-setupchecks the environment and the connection.If the marketplace add stalls (it clones over SSH on machines that have a GitHub SSH key configured but no access, and waits on the key prompt), use a local clone instead:
git clone https://github.com/erickcxc/dograh-ctl.git claude plugin marketplace add ./dograh-ctl claude plugin install dograh-ctl@dograh-ctl
-
Any MCP client:
dograh-ctl mcp-configprints theclaude mcp addline and the JSON block. -
Shell-driving agents: every command takes
--json; exit codes are stable (2 config, 1 remote);AGENTS.mdhas the conventions. -
Safety for autonomous use: tools that place calls (
runs_trigger,campaigns_start) are annotated destructive so clients confirm; writes are idempotent read-modify-write; payloads are scrubbed of keys;keys create/revokeandnumbers removeare CLI-only on purpose.
Dograh mounts its own MCP server at {DOGRAH_BASE_URL}/api/v1/mcp (Streamable HTTP, same API key). Its tools are for authoring: create and save workflows, list node types, search the docs, pull the voice-prompting guide.
dograh-ctl serve is the operations plane over stdio: list agents, place a call, read a transcript, latency stats, route numbers, flip models, watch a campaign. Point Claude Code (or any MCP client) at both and an agent can build a voice agent, call it, and read what happened.
{ "mcpServers": { "dograh-ops": { "command": "dograh-ctl", "args": ["serve"] } } }Shapes are taken from the Dograh source at dograh-hq/dograh@b32187d8 (2026-08-20) and pinned in tests/fixtures. Ten endpoints are Dograh's stable SDK contract; the rest are dashboard-internal and may drift between Dograh releases, which is why every command is mocked-HTTP tested and the fixtures cite their schema.
| Status | Commands |
|---|---|
| Live-verified on a self-hosted instance | ping, agents list/get/create/set-prompt/rename/set-model/validate/publish, models show/set, runs list/latency/chat/transcript, numbers list/assign, telephony configs/providers, tools list, keys list, campaigns list, serve (stdio handshake + live tool call) |
| Verified against the upstream schemas with mocked HTTP | runs trigger/recording, numbers add/remove, keys create/revoke, campaigns create/start/pause/status |
Live-verified rows move as commands are exercised against a real instance; nothing is listed as live-verified unless it was.
- Thin
httpxclient with theX-API-Keyheader;DOGRAH_BASE_URLandDOGRAH_API_KEYfrom the environment. typerandrich; one output module so tables and--jsonnever drift; one error path so no command shows a traceback.- Talks only to your own self-hosted Dograh. This is a control layer on top of Dograh; it never vendors or republishes Dograh's code.
- Tests:
uv run pytest(respx-mocked HTTP, fixtures mirror the upstream schemas). CI runs lint + tests on Python 3.10 and 3.12.
The whole operations surface of a self-hosted Dograh instance, in one tool: 9 command groups, 32 commands, every one of them tested, and the same verbs exposed to agents through serve. Day 8 shipped the skeleton (ping, agents, runs, numbers); Day 9 completed the map and tagged v0.2.0.
Designed and built live on the AI by Erick stream (one-hour build challenge, Days 8 and 9), as the engine-first pivot into voice.
Daily builds: https://www.youtube.com/channel/UCWCXKXvNtNbKPkeK_t5CZlg
I build agentic systems like this for businesses. Reach me through the channel.
MIT

