An AI-agent-first CLI for Trello, modeled on gh. It
speaks JSON cleanly, keeps data on stdout and messaging on stderr, and uses
predictable exit codes — so it is equally easy to use by hand, to script in a
pipeline, or to drive from an AI agent.
trello card list --board "Roadmap" --json --jq '.[] | select(.due != null) | .name'- Install
- Quick start
- Authentication
- Usage — examples for every command
- Command reference
- Output model (
--json/--fields/--jq) - Driving from an AI agent or script
- Stream contract
- Exit codes
- Development
go install github.com/Broco98/trello-cli/cmd/trello@latestThis installs a trello binary into your $GOBIN (or $GOPATH/bin). Make sure
that directory is on your PATH. Requires Go 1.22+.
Or build from a checkout:
git clone https://github.com/Broco98/trello-cli.git
cd trello-cli
go build -o trello ./cmd/trello# 1. Get a Trello API key + token at https://trello.com/app-key
export TRELLO_API_KEY=your_key
export TRELLO_TOKEN=your_token
# 2. See your boards and pick one as the default
trello board list
trello board set-default "Roadmap" # now --board can be omitted
# 3. Look around
trello list list # lists (columns) in the default board
trello card list --list "To Do" # cards in one list
# 4. Get work done
trello card create --list "To Do" --name "Write the README" --due 2026-07-01
trello card move "Write the README" --list "In Progress"
trello card comment "Write the README" --message "draft pushed"
trello card close "Write the README" # archiveThat's the whole loop: discover boards/lists, then create, move, annotate, and archive cards.
You need a Trello API key and token (create them at https://trello.com/app-key). There are two ways to provide them.
export TRELLO_API_KEY=...
export TRELLO_TOKEN=...
trello board listThe API key is passed with --api-key. The token is read from stdin (so it
never lands in your shell history) or from a file via --token-file:
# token piped on stdin
printf '%s' "$MY_TRELLO_TOKEN" | trello auth login --api-key "$MY_TRELLO_API_KEY"
# or from a file
trello auth login --api-key "$MY_TRELLO_API_KEY" --token-file ./token.txtCredentials are stored in your OS keychain. If the keychain is unavailable,
trello falls back to a plaintext file at
$XDG_CONFIG_HOME/trello-cli/credentials (mode 0600) and prints a warning to
stderr — prefer environment variables or a working keychain in that case.
trello auth status # show the active account and which credential source is in use
trello auth logout # remove stored credentialsFor every value (key and token independently), resolution is:
command flag > environment variable (TRELLO_API_KEY / TRELLO_TOKEN) > stored (keychain / fallback file)
If no key/token can be resolved, the command exits with code 3 (auth error).
Every command follows trello <noun> <verb> [flags] (like gh). Boards, lists,
and cards can be named by id or by name — names are resolved against the
relevant board.
trello board list # all your boards
trello board view "Roadmap" # one board, by name
trello board view 5f2a1b3c4d5e6f7a8b9c0d1e # ...or by id
trello board set-default "Roadmap" # remember it; --board becomes optionaltrello list list # lists in the default board
trello list list --board "Roadmap" # lists in a specific boardNote: the noun is
list(a Trello List / column) and the verb is alsolist, so listing them reads astrello list list. This is intentional — it keeps the verb vocabulary uniform across every noun.
trello card list --board "Roadmap" # every card on a board
trello card list --list "To Do" # cards in one list
trello card view "Write the README" # a single card by name (within default board)
trello card view 61f0c... --board "Roadmap" # by name needs a board; by id does not# create (--list and --name are required)
trello card create --list "To Do" --name "Ship v1" \
--desc "cut the first release" --due 2026-07-01 --label bug --label urgent
# edit any subset of fields (only the flags you pass are changed)
trello card edit "Ship v1" --name "Ship v1.0" --due 2026-07-15
# move to another list
trello card move "Ship v1.0" --list "In Progress"
# comment
trello card comment "Ship v1.0" --message "blocked on review"
# add / remove a label (exactly one of --add / --remove)
trello card label "Ship v1.0" --add urgent
trello card label "Ship v1.0" --remove bug
# archive (close)
trello card close "Ship v1.0"trello auth login --api-key "$KEY" --token-file ./tok # store credentials
trello auth status # who am I, which source
trello auth logout # forget credentials| Command | Verb | Description |
|---|---|---|
auth |
login |
Store credentials (--api-key; token from stdin or --token-file) |
logout |
Remove stored credentials | |
status |
Show active account and credential source | |
board |
list |
List your boards |
view <board> |
View a board by id or name | |
set-default <board> |
Set the default board used when --board is omitted |
|
list |
list |
List the lists in a board (--board) |
card |
list |
List cards in a board or list (--board, --list) |
view <card> |
View a card by id, or by name within a board (--board) |
|
create |
Create a card (--list, --name required; --board, --desc, --due, --label) |
|
edit <card> |
Edit a card's fields (--name, --desc, --due, --list, --board) |
|
move <card> |
Move a card to another list (--list required, --board) |
|
comment <card> |
Add a comment (--message required, --board) |
|
label <card> |
Add or remove a label (--add xor --remove, --board) |
|
close <card> |
Archive (close) a card (--board) |
The default board (set via board set-default) is used whenever --board is not
given. Configuration is stored at $XDG_CONFIG_HOME/trello-cli/config.yml.
Global flags (--json, --fields, --jq, --no-color) work on every command.
Run trello <command> --help for full per-command help.
By default commands render compact, human-readable tables. When stdout is a TTY, JSON output is pretty-printed; when piped, it is compact — so scripts and agents get stable machine output for free.
| Flag | Effect |
|---|---|
--json |
Emit JSON instead of a table (all fields unless --fields is given) |
--fields a,b,c |
With --json, project only the named fields |
--jq <expr> |
Filter the JSON output with a built-in jq expression (no jq binary needed) |
--no-color |
Disable color output |
trello board list --json
trello card list --board "Roadmap" --json --fields id,name,due
trello card list --board "Roadmap" --json --jq '.[] | select(.due != null) | .name'Color is also suppressed automatically when NO_COLOR is set, when TERM=dumb,
or when stdout is not a terminal. TTY detection only affects cosmetics
(pretty vs compact JSON, color); it never changes the data schema — JSON is
emitted only when you pass --json.
This is what trello-cli is built for. Two properties make it robust to automate:
- Always-parseable output. Add
--jsonand read stdout; never scrape tables. - Branch on exit codes, not on text. See the table below.
# create a card and capture its id, with no prose to strip.
# built-in --jq emits JSON-encoded values, so strip the quotes for a raw scalar:
id=$(trello card create --list "To Do" --name "auto task" --json --jq '.id' | tr -d '"')
# resolve-and-branch without parsing error strings
if trello card view "Some Task" --json >/tmp/card.json 2>/dev/null; then
echo "found: $(jq -r .name /tmp/card.json)"
else
case $? in
4) echo "no such card" ;;
5) echo "name is ambiguous — use the id" ;;
3) echo "not authenticated" ;;
esac
fiFor agents, prefer passing ids (24-char hex) to skip name resolution
entirely, and keep credentials in TRELLO_API_KEY / TRELLO_TOKEN so no
interactive login is needed.
- stdout carries data only — table rows or JSON. Nothing else.
- stderr carries all messaging — confirmations (e.g. "Saved Trello credentials.", create/move/close confirmations), warnings, and errors, including the candidate list when a name is ambiguous.
So you can always pipe stdout into jq, another tool, or a file without
stripping prose, and 2>/dev/null hides chatter without losing data.
| Code | Name | Meaning |
|---|---|---|
| 0 | OK | Success |
| 1 | Error | Generic / runtime error |
| 2 | Usage | Bad invocation (unknown flag, missing/extra arguments) |
| 3 | Auth | Missing or invalid credentials |
| 4 | Not found | Referenced board/list/card did not match anything |
| 5 | Ambiguous | A name matched more than one object |
With --json, errors are emitted as a structured envelope on stderr:
{"error":{"code":4,"message":"card \"roadmap\" not found"}}These are intentionally left out for now (YAGNI) to keep the surface small. They are recorded here so the boundary is explicit, not forgotten — each can be added later without reworking what exists.
Skills feature (deliberately deferred):
trello skill remove/trello skill upgrade— for now you can re-install with--force; lifecycle management beyond that is out of scope.- Remote skill registry / installing third-party skills — only the skills embedded in the binary are installable today.
Trello surface (deferred from the MVP):
- Checklists, member assignment, attachments.
- Global search across boards.
- A natural-language wrapper (e.g.
trello "add a card for the launch").
Output / cosmetics:
- ANSI terminal color. The
--no-colorflag and theNO_COLOR/TERM=dumb/ non-TTY rules are already honored; color itself is not emitted yet. The current TTY cosmetic is JSON pretty-print on a terminal vs compact when piped.
The command tree and client are structured so each of these adds as a new noun/verb/method without refactoring existing packages.
go build -o trello ./cmd/trello # build the binary
go test ./... # run the full test suite
go vet ./... # static checksThe design and implementation plan live under
docs/superpowers/. Architecture: a thin Cobra command
layer (internal/cli) over a pure net/http Trello client (internal/trello),
with cross-cutting packages for output (internal/output), credentials
(internal/auth), config (internal/config), and name→id resolution
(internal/resolve).