{"id":"c098fb0b-7bd5-42d0-91db-1cb9ebc551a0","slug":"wootctl","kind":"mcp","name":"wootctl","summary":"A fast, scriptable CLI for the full Chatwoot API — 144/144 operations, profiles, keyring auth, MCP server, agent guardrails","owner":"jjuanrivvera","repoUrl":"https://github.com/jjuanrivvera/wootctl","license":"MIT","licenseTier":"permissive","trust":"community","stars":1,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-07-10T18:57:09.000Z","addedAt":"2026-10-29T06:05:54.091Z","logoUrl":"https://avatars.githubusercontent.com/u/84686701?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["cloud-infra"],"tags":["ai-agents","chatwoot","cli","customer-support","golang"],"runtime":"go","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-29T06:06:15.074Z","sample":false,"url":"https://conduits.dev/tools/wootctl","language":"Go","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"<div align=\"center\">\n\n# wootctl\n\n[![CI](https://github.com/jjuanrivvera/wootctl/actions/workflows/ci.yml/badge.svg)](https://github.com/jjuanrivvera/wootctl/actions/workflows/ci.yml)\n[![Release](https://img.shields.io/github/v/release/jjuanrivvera/wootctl)](https://github.com/jjuanrivvera/wootctl/releases/latest)\n[![Coverage](https://img.shields.io/badge/coverage-%E2%89%A580%25-brightgreen)](https://github.com/jjuanrivvera/wootctl/actions/workflows/ci.yml)\n[![Go Reference](https://pkg.go.dev/badge/github.com/jjuanrivvera/wootctl.svg)](https://pkg.go.dev/github.com/jjuanrivvera/wootctl)\n[![Go version](https://img.shields.io/github/go-mod/go-version/jjuanrivvera/wootctl)](go.mod)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/jjuanrivvera/wootctl)\n[![Built with cliwright](https://img.shields.io/badge/built_with-cliwright-1f6feb)](https://cliwright.jjuanrivvera.com)\n\n**A fast, scriptable CLI for the full Chatwoot API — application, platform, and public client groups.**\n\n[Documentation](https://jjuanrivvera.github.io/wootctl/) · [Commands](https://jjuanrivvera.github.io/wootctl/commands/)\n\n\n![wootctl in action](assets/demo.gif)\n\n</div>\n\n---\n\nA fast, scriptable CLI for the full [Chatwoot](https://www.chatwoot.com) API.\n\n`wootctl` wraps every operation Chatwoot documents — 144/144 across the application,\nplatform, and public client APIs — with named profiles for working across several\ninstances, OS-keyring token storage (with an encrypted-file fallback for headless\nhosts), table/json/yaml/csv output, and an MCP server so AI agents can drive it safely.\n\n```console\n$ wootctl conversations list --status open\nID  INBOX_ID  STATUS  PRIORITY\n42  3         open    high\n57  1         open\n\n$ wootctl messages create 42 --content \"On it — checking now.\"\n$ wootctl conversations toggle-status 42 --status resolved\n```\n\n## Install\n\n```bash\n# Install script (macOS / Linux) — downloads the release binary, verifies its checksum\ncurl -fsSL https://raw.githubusercontent.com/jjuanrivvera/wootctl/main/install.sh | sh\n\n# Homebrew (macOS / Linux)\nbrew install jjuanrivvera/wootctl/wootctl-cli\n\n# Scoop (Windows)\nscoop bucket add wootctl https://github.com/jjuanrivvera/scoop-wootctl\nscoop install wootctl\n\n# Go\ngo install github.com/jjuanrivvera/wootctl/cmd/wootctl@latest\n```\n\ndeb/rpm/apk packages and prebuilt archives are on the\n[releases page](https://github.com/jjuanrivvera/wootctl/releases). Releases are\ncosign-signed and ship SBOMs.\n\n## Setup\n\n```bash\nwootctl auth login\n```\n\nYou are prompted for your instance URL and `api_access_token` (Chatwoot → Profile\nSettings → Access Token; input is hidden). The token is verified live, the account is\nselected, and everything is saved: the token in your OS keyring, the rest in\n`~/.wootctl-cli/config.yaml`.\n\nHeadless host with no keyring? Set `WOOTCTL_KEYRING_PASSWORD` and tokens go to an\nAES-256-GCM encrypted file instead. CI? `WOOTCTL_API_KEY` overrides everything.\n\n### Profiles\n\nWork across several Chatwoot instances (or accounts) by saving each as a profile:\n\n```bash\nwootctl --profile staging auth login     # save a second instance\nwootctl config list-profiles             # see them\nwootctl config use staging               # switch the default\nwootctl --profile staging convs list     # one-off override\n```\n\nA profile bundles base URL + account id + tokens, so switching profiles switches\neverything at once. `WOOTCTL_PROFILE` selects one per shell.\n\n## The surface\n\n| Group | Commands |\n|---|---|\n| Conversations | `list · meta · create · get · update · filter · labels · add-labels · assign · toggle-status · toggle-priority · toggle-typing · set-custom-attributes · reporting-events` |\n| Messages | `list · create (with --attachment multipart) · delete` |\n| Contacts | `list · create · get · update · delete · search · filter · merge · conversations · contactable-inboxes · create-contact-inbox · labels · add-labels` |\n| Inboxes | `list · create · get · update · agent-bot · set-agent-bot · members · add/update/remove-members` |\n| Teams | `list · create · get · update · delete · members · add/update/remove-members` |\n| Reports | `overview · summary · account/agent-conversations · first-response-time-distribution · inbox-label-matrix · outgoing-messages-count · agent/channel/inbox/team-summary · events` |\n| Also | `account · agents · agent-bots · audit-logs · automation-rules · canned-responses · custom-attributes · custom-filters · integrations · labels · portals · profile · webhooks · csat` |\n| `platform …` | accounts, account-users, agent-bots, users (+ sso-link) — platform app token |\n| `client …` | the public, unauthenticated contact-facing API (inbox, contacts, conversations, messages) |\n\nAnything not wrapped (there is nothing today) is reachable via the escape hatch:\n\n```bash\nwootctl api GET api/v2/accounts/1/reports/summary -q since=1780272000\n```\n\nThe full command reference lives in [docs/commands](docs/commands/wootctl.md).\n\n## Output and scripting\n\n```bash\nwootctl contacts search --q ana -o json | jq '.[0].email'\nwootctl labels list -o id | xargs -n1 wootctl labels get\nwootctl conversations list --all --filter status=open -o csv > open.csv\nwootctl agents list --columns name,email\nwootctl conversations list --jq '.[3].meta.sender.name'\n```\n\n`table` (default, TTY-colored, `NO_COLOR` honored), `json`, `yaml`, `csv`\n(formula-injection-sanitized), and `id` (one per line, pipe-friendly). `--all` walks\nevery page. `--dry-run` prints the exact curl (token redacted) instead of calling:\n\n```console\n$ wootctl labels create --title vip --dry-run\ncurl -X POST 'https://…/api/v1/accounts/1/labels' -H 'api_access_token: REDACTED' \\\n  -H 'Content-Type: application/json' -d '{\"title\":\"vip\"}'\n```\n\n## AI agents\n\n`wootctl` is agent-ready in both directions:\n\n```bash\nwootctl mcp claude enable    # expose 125 annotated MCP tools (reads/writes/destructive)\nwootctl agent guard --host claude-code --write   # install guardrails for agents using Bash\n```\n\nThe MCP surface excludes auth/config/profile switching and every secret flag. The\nguard hard-blocks irreversible operations (deletes, `contacts merge`) — including\nevery cobra alias path and the raw `api` hatch for write methods — with a PreToolUse\nhook that survives quoting tricks and path-prefixed binaries. `codex` and `opencode`\ntargets are included.\n\n## Backup, restore & sync (beyond the API)\n\nPast the raw endpoints, wootctl treats your account **config** as something you can version and\nmove between instances — labels, canned responses, custom attributes, custom filters,\nautomation rules, teams, webhooks, and agent bots (never conversations/contacts/messages,\nwhich are live data).\n\n```bash\n# dump config to a git-friendly directory (one YAML file per kind, writable fields only)\nwootctl backup --dir ./chatwoot-config\ngit -C ./chatwoot-config add -A && git -C ./chatwoot-config commit -m \"chatwoot config\"\n\n# reconcile a backup back into the account: create missing, update changed, skip unchanged\nwootctl restore --dir ./chatwoot-config --dry-run     # always preview first\nwootctl restore --dir ./chatwoot-config\nwootctl restore --dir ./chatwoot-config --only labels --prune   # also delete drift\n\n# the multi-instance payoff the official CLI can't do: promote config between instances\nwootctl sync --to production --dry-run\nwootctl sync --to production --only canned-responses,labels\nwootctl --profile staging sync --to production --prune\n```\n\nMatching is by natural key (title, short_code, name, url, attribute_key); \"unchanged\" compares\nonly writable fields, so `id`/timestamps never cause phantom updates. A key that appears twice\nin an account is skipped and never pruned — wootctl won't act on an ambiguous match. `restore`\nand `sync` are classified destructive, so `wootctl agent guard` hard-blocks them for AI agents.\n\n## vs the official `chatwoot` CLI\n\nThe official [Chatwoot CLI](https://developers.chatwoot.com/cli) is good at what it\ncovers, and if you only drive one instance's conversations it may be all you need.\n`wootctl` exists because we needed more:\n\n- **Coverage**: wootctl wraps all 144 documented operations (application + platform +\n  public client APIs), enforced by a spec-completeness gate in CI. The official CLI\n  covers the core conversation workflow.\n- **Multi-profile**: first-class named profiles across instances/accounts.\n- **Headless hosts**: encrypted-file keyring fallback when no OS keyring exists (VPS,\n  containers).\n- **Agent surface**: MCP server with safety annotations + generated guardrails.\n- **Beyond the API**: git-friendly `backup`/`restore` of account config and cross-instance\n  `sync` — promote labels/canned-responses/automation between instances.\n- **Scripting**: json/yaml/csv/id output, `--jq`, `--dry-run` curls, `--all` pagination.\n\nWhere the official CLI is genuinely better: it is first-party (tracks new endpoints the\nmoment they are documented by the same team), has upstream support, and its TUI-style\nconversation flow is more polished for interactive triage. Both can coexist — the\nbinaries do not collide.\n\n## Development\n\n```bash\nmake build      # bin/wootctl\nmake check      # fmt + vet + lint + tests\nmake verify     # the full deterministic gate (spec-check, completeness, coverage, DoD)\n```\n\nThe CLI surface is pinned to [api-manifest.json](api-manifest.json), derived from\nChatwoot's own OpenAPI spec; `make spec-check` fails if they diverge, and\n`make spec-completeness` fails if the manifest covers less than the enumerated API.\nDesign decisions are recorded in [DECISIONS.md](DECISIONS.md).\n\n## License\n\nMIT\n"}