A standalone Go CLI for Asana, ported from the pi-extensions Asana extension so
any agent (or human/script) can invoke Asana operations from the shell. Output is
JSON by default for deterministic machine parsing; pass --human for readable
summaries.
brew tap dtonair/tap
brew install asana-cliTo upgrade later: brew upgrade asana-cli.
go install github.com/dtonair/asana-cli/cmd/asana-cli@latestThis installs the asana-cli binary into $(go env GOBIN) (or $(go env GOPATH)/bin); make sure that directory is on your PATH.
go build -o asana-cli ./cmd/asana-cli
# or
go install ./cmd/asana-cliRequires Go 1.22+. The only third-party dependency is spf13/cobra.
Check the installed version with asana-cli --version.
Credentials come from environment variables or a YAML config file. Environment variables take precedence over the file.
export ASANA_ACCESS_TOKEN="your-asana-personal-access-token" # required
export ASANA_DEFAULT_WORKSPACE="workspace-gid" # optionalIf ASANA_ACCESS_TOKEN is not set, the CLI reads ~/.config/asana-cli.yaml
(override the path with $ASANA_CONFIG, or relocate via $XDG_CONFIG_HOME):
# ~/.config/asana-cli.yaml
access_token: your-asana-personal-access-token # required
default_workspace: workspace-gid # optionalEach value is used only when the corresponding env var is unset, so you can keep
a token in the file and still override it per-shell with ASANA_ACCESS_TOKEN.
Keep the file private (chmod 600 ~/.config/asana-cli.yaml).
default_workspace/ASANA_DEFAULT_WORKSPACE is optional, but workspace-scoped
commands require either it or an explicit --workspace-gid.
Recommended token scopes: users:read, workspaces:read, projects:read,
tasks:read, stories:read, and stories:write for comment-on-task.
| Flag | Default | Description |
|---|---|---|
--human |
off | Print human-readable summaries instead of JSON |
--verbose |
off | Log request method + path to stderr (never the token) |
--timeout |
30s |
HTTP request timeout |
| Command | Asana endpoint | Notes |
|---|---|---|
me |
GET /users/me |
|
list-workspaces |
GET /workspaces |
--limit, --opt-fields |
list-projects |
GET /workspaces/{ws}/projects |
--workspace-gid, --limit, --opt-fields |
search-tasks |
GET /workspaces/{ws}/tasks/search |
--text, --assignee, --completed, --limit, --opt-fields (may require premium) |
get-task |
GET /tasks/{gid} |
--task-gid (required), --opt-fields |
list-task-stories |
GET /tasks/{gid}/stories |
--task-gid (required), --limit, --opt-fields |
comment-on-task |
POST /tasks/{gid}/stories |
--task-gid, --text (both required). The only write command. |
--limit is bounded to 1..100 (default 20). List/search commands paginate
internally (page size 50, up to 10 pages, capped at --limit).
--completed is tri-state: omitted entirely unless you pass it
(--completed=true or --completed=false).
Success (stdout):
{
"ok": true,
"data": <Asana resource (object) or array of resources>
}data is the unwrapped Asana payload: an object for single-resource commands
(me, get-task, comment-on-task), an array for list/search commands.
Error (stderr, non-zero exit):
{
"ok": false,
"error": {
"message": "Asana resource not found. ...",
"status": 404,
"method": "GET",
"path": "/tasks/999"
}
}status/method/path are present only for HTTP errors. With --human, errors
print as a plain message line instead.
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Runtime error (HTTP non-2xx, network failure, timeout) |
2 |
Usage/config error (missing token, missing required flag, bad --limit, no workspace) |
asana-cli me
asana-cli list-workspaces --limit 50
asana-cli list-projects --workspace-gid 12345
asana-cli search-tasks --text "release" --completed=false
asana-cli get-task --task-gid 12345 --human
asana-cli list-task-stories --task-gid 12345
asana-cli comment-on-task --task-gid 12345 --text "Taking a look."go test ./...Tests run against an in-process httptest server; no network or real token is
required. The API base URL is overridable via the ASANA_API_BASE environment
variable (test-only seam; not a user-facing flag).
The token is read from the environment or, as a fallback, from
~/.config/asana-cli.yaml. The CLI never writes the token to disk itself
(you create the config file) and never includes it in any rendered output,
error, or --verbose log line. If you store the token in the config file,
restrict its permissions (chmod 600). All requests go over HTTPS to
https://app.asana.com/api/1.0.