Use the Hydrant CLI
The Hydrant CLI calls the same tools your agent does, from a terminal or a CI job. Use it to read the board without opening a browser, or to have a pipeline move an issue when the work it describes lands. It’s the @hydrantdev/cli (opens in a new tab) package on npm: no dependencies, and it never stores the key.
Before you start
Section titled “Before you start”- An agent key. Create one under Settings › Agents › Access; Agent keys covers the details. A Read only key can run
list,view,toolsand every read tool. Anything that writes needs Read and write. - Node 20.12 or later.
node --versiontells you. - The right package name. Bare
npx hydrantruns someone else’s package. Always ask for@hydrantdev/cli.
Run it
Section titled “Run it”- Put the key in the environment.
read -s HYDRANT_KEY(paste, then Return) keeps it out of your shell history; thenexport HYDRANT_KEY. - Run
npx @hydrantdev/cli tools. That lists every tool the key can call, one line each. - If you’ll use it often,
npm i -g @hydrantdev/cliinstalls thehydrantcommand. The examples below use that name;npx @hydrantdev/cliworks anywherehydrantdoes.
HYDRANT_URL defaults to https://hydrant.dev. --key and --url override the environment for one run.
Read issues
Section titled “Read issues”hydrant list # open issues, newest firsthydrant list --status "in progress" --assignee adahydrant list --view all --all --q export # include Done and Canceledhydrant view 12 # one issue and its latest activityNames match case-insensitively. An unknown status, person, label, project or milestone lists the valid ones instead of guessing.
Call any tool
Section titled “Call any tool”hydrant tools get_issue # one tool's input schemahydrant call get_workspacehydrant call list_issues '{"limit":5}'echo '{"limit":5}' | hydrant call list_issues -Arguments are one JSON object. Only - reads them from stdin, so a script with an open pipe never hangs waiting.
Write tools need a request id. Leave it out and the CLI makes one and prints it to stderr. If a write fails partway, retry with --request-id and that id, and it lands once. Writes that don’t bite explains why.
Script it
Section titled “Script it”list, view and call print compact JSON when piped or with --json; tools needs --json. hydrant list --json | jq '.issues[].title' does what it looks like.
In GitHub Actions, keep the key in a repository secret. This step moves an issue to Done; update_issue needs the issue’s current version, so it reads that first:
- name: Mark the Hydrant issue done env: HYDRANT_KEY: ${{ secrets.HYDRANT_KEY }} ISSUE_ID: 00000000-0000-4000-8000-000000000000 # the issue's id run: | version=$(npx --yes @hydrantdev/cli call get_issue "{\"issueId\":\"$ISSUE_ID\"}" | jq '.data.issue.version') npx --yes @hydrantdev/cli call update_issue "{\"issueId\":\"$ISSUE_ID\",\"version\":$version,\"patch\":{\"status\":\"done\"}}"Pin a version, like @hydrantdev/cli@0.2.0, if you’d rather upgrade on purpose.
What you should see
Section titled “What you should see”hydrant list in a terminal prints a table, in colour unless NO_COLOR is set:
# Status Priority Assignee Title#12 In Progress High Ada Lovelace Rename the export button#3 Backlog Urgent — Fix the login copyhydrant view 12 prints the issue’s fields, its description and the five latest activity entries.
call prints what the tool returned. Piped, it’s one line of JSON; in a terminal, indented. The tool’s answer sits under data:
{"workspace":{"id":"…","name":"Acme","role":"member"},"kind":"receipt","data":{"issue":{"number":12,"status":"done","version":3}}}A write without --request-id also prints one line to stderr, which you keep in case you need to retry:
request id: 980d643b-1d14-4ff4-8f77-1c1a79dfe093hydrant alone prints the overview. hydrant <command> --help gives an example for every flag that command takes.
If it goes sideways
Section titled “If it goes sideways”Every failure prints one line to stderr: what happened, then what to do. Nothing goes to stdout. Piped or with --json, that line is a JSON object with code, message and hint. The exit code says which kind of failure it was:
| Code | Means | The hint says |
|---|---|---|
| 0 | It worked. | |
| 1 | The tool refused: not found, invalid arguments, not allowed for your role, or too large. | What to fix, such as checking the arguments against hydrant tools <name>. |
| 2 | Usage: unknown command, flag or name, invalid JSON, or no key. | Run hydrant <command> --help, or set HYDRANT_KEY. |
| 3 | Key refused, read-only key on a write, origin refused, or the key’s owner lost access. | Check the key, use a read-and-write key, or fix HYDRANT_URL. |
| 4 | Conflict: someone changed it first. | Reread it and send the current version. |
| 5 | Rate limited, after one automatic retry. | Try again in the number of seconds it gives. |
| 6 | Hydrant is unavailable or unreachable. | Try again. For a write, reuse its --request-id. |
- Exit 2 and “must be an origin”.
HYDRANT_URLtakes an origin only:https://hydrant.dev, with no path, no query and no trailing/api/mcp. Plainhttpworks only for a local server. - Exit 3 and “HYDRANT_URL must be the exact origin the key was issued for.” The shape is fine but Hydrant refused it: use the exact origin the key came from, usually
https://hydrant.dev. - Exit 3 on a write with a read-only key. Create a Read and write key under Settings › Agents › Access and revoke the old one if nothing else uses it.
- Exit 5. A rate-limited request never runs, so the CLI waits and sends it once more when the wait is 30 seconds or less. If that fails too, or the wait is longer, it stops and tells you how long to wait. A command that makes several requests, like
listacross pages, can wait more than once. - Exit 6 after a write. The write may have gone through. Retry with the
--request-idfrom stderr; Hydrant applies it once either way. - The key leaked. Keys live in Settings › Agents › Access, nowhere else. Revoke it there, now. The CLI never writes the key to disk, but your shell history or CI logs might have it.
- Something else. When an agent gets stuck covers the errors the CLI passes through from Hydrant.