asana-api-cli
Call any Asana endpoint from your shell — no throwaway Python script
needed. asana-api <group> <command> turns every method of the official
python-asana SDK into a
command, so you can read, create, and inspect Asana data one line at a time.
And because each command maps 1:1 to an SDK method, the call you work out in the shell is the call you write in Python:
# Work it out interactively...
asana-api tasks get-tasks --project 123 --opt-fields name,assignee.name
# ...then drop the same call into your app:
asana.TasksApi(client).get_tasks({"project": "123", "opt_fields": "name,assignee.name"})
Or skip the translation entirely: asana-api --generate-python … writes that
Python for you (see Usage).
Why asana-api-cli
- Explore the whole API from the shell. Every method of every
*Apiclass is a command — list tasks, create a project, poll events — with no script and no boilerplate. - What you learn transfers to Python. Flags map to SDK method
parameters, and JSON output matches the SDK's response shape — so a
working shell call becomes a working SDK call. Each option's
--helpeven names where its value lands in the SDK. - Always matches your SDK version. The command tree is built at startup
by introspecting the installed
asanapackage. Install it beside your project's SDK and the two stay in lock-step — new upstream methods appear the momentpip install -U asanalands, with noasana-api-clirelease and no stale docs. - Shell-native ergonomics. JSON / table / CSV / text output,
jqfiltering (--query), automatic pagination, structured error envelopes, and--debugrequest tracing with the auth token masked.
Installation
pip install asana-api-cli
For best results, install asana-api-cli into the same Python environment
that holds your project's python-asana so the CLI surface tracks the
exact SDK version your application uses (see As a
dev-dependency below).
As a dev-dependency
If your project already uses python-asana, add asana-api-cli to your dev
group so the CLI tracks the same SDK version your application code uses:
# pyproject.toml
[project]
dependencies = ["asana>=5.2,<6"]
[dependency-groups] # uv
dev = ["asana-api-cli"]
# Poetry
[tool.poetry.group.dev.dependencies]
asana-api-cli = "*"
After uv sync (or equivalent), asana-api resolves to the project's
.venv and introspects whatever asana version is locked there. Calls
prototyped with asana-api tasks ... translate directly to the SDK calls
you'll write in your app.
Installing globally with pipx
If you would rather isolate asana-api-cli from any project's dependencies
— for example, when you administer Asana from the shell without writing
Python — install it with pipx:
pipx install asana-api-cli
In this setup the CLI uses the python-asana version pipx resolved when
installing asana-api-cli; pipx upgrade asana-api-cli updates only
asana-api-cli itself, not the bundled python-asana. To pull a newer
python-asana into the existing pipx install without reinstalling the
CLI:
pipx runpip asana-api-cli install -U "asana<6"
Keep the <6 bound — it is the SDK range asana-api-cli supports. A bare
install -U asana does not honor that requirement: pip would install a future
major version anyway (reporting only a dependency-conflict error), leaving the
CLI on an SDK it does not support.
The next asana-api run sees the new SDK and any newly added methods
automatically.
Environment variables
| Name | Required | Description |
|---|---|---|
ASANA_ACCESS_TOKEN |
Yes (at runtime only) | Asana personal access token |
ASANA_DEFAULT_WORKSPACE |
No | Default workspace GID for endpoints that require it |
The token can be issued from the
Asana Developer Console.
No token is needed for --help or command-line parsing errors, including a
--query jq expression that does not compile. (A jq expression that compiles
but fails on the actual response surfaces only after the API call.)
export ASANA_ACCESS_TOKEN="2/12345..."
export ASANA_DEFAULT_WORKSPACE="12345678" # optional
On Windows PowerShell:
$env:ASANA_ACCESS_TOKEN = "2/12345..."
$env:ASANA_DEFAULT_WORKSPACE = "12345678" # optional
PowerShell handles native-command input and output encodings its own way — especially Windows PowerShell 5.1, which also strips the double quotes from inline JSON arguments. See Windows and PowerShell before scripting with it.
Shell completion
asana-api is built with Click, which supports dynamic shell completion.
To enable it, add the line for your shell to its startup file:
# bash: ~/.bashrc
eval "$(_ASANA_API_COMPLETE=bash_source asana-api)"
# zsh: ~/.zshrc
eval "$(_ASANA_API_COMPLETE=zsh_source asana-api)"
# fish: ~/.config/fish/config.fish
_ASANA_API_COMPLETE=fish_source asana-api | source
Then reload the shell (e.g. source ~/.bashrc, or open a new terminal).
Pressing <TAB> after asana-api will now complete subcommands and options.
Click does not generate PowerShell completion. Windows users can install
completion under WSL or Git Bash using the bash_source line above.
Usage
# Version and help
asana-api --version
asana-api --help
asana-api tasks --help
asana-api tasks get-tasks --help
# List workspaces
asana-api workspaces get-workspaces
# List up to 50 projects (workspace comes from $ASANA_DEFAULT_WORKSPACE)
asana-api projects get-projects-for-workspace --item-limit 50
asana-api projects get-projects --workspace <WORKSPACE_GID> --item-limit 50
# List every task in a project (walks every page by default)
asana-api tasks get-tasks --project <PROJECT_GID>
# Preview the first few items
asana-api tasks get-tasks --project <PROJECT_GID> --item-limit 5
# One HTTP call: return the first page + the next_page cursor
asana-api tasks get-tasks --project <PROJECT_GID> --limit 100 --full-payload
# Single task
asana-api tasks get-task --task <TASK_GID>
# Create a task (body is a JSON string)
asana-api tasks create-task --body '{"data":{"name":"new task","projects":["<PROJECT_GID>"]}}'
# Output formats — non-JSON formats render one row per item. The default
# auto-paginating output is a flat list, so it is directly rowable; under
# --full-payload, unwrap the `{"data": [...]}` envelope first with `--query '.data'`
# (and pass --limit: Asana rejects an unpaginated request over ~1000 items).
asana-api tasks get-tasks --project <PROJECT_GID> --output table
asana-api tasks get-tasks --project <PROJECT_GID> --limit 100 --full-payload --query '.data' --output csv
# CSV output is UTF-8 without a BOM by default. Pass --csv-bom for Excel on
# Windows, which otherwise displays non-ASCII characters as garbled text.
# (In Windows PowerShell 5.1, redirect via cmd.exe — see docs/usage.md.)
asana-api tasks get-tasks --project <PROJECT_GID> --output csv --csv-bom > tasks.csv
# --output none suppresses the success payload — handy for side-effect-only
# calls (delete/update) where only the exit code matters. A --query still runs,
# so it can still fail (exit 2) even when output is silenced.
asana-api tasks delete-task --task <TASK_GID> --output none
Don't hand-translate the call yourself — --generate-python does it for you. It
prints a standalone python-asana script equivalent to the command instead of
running it (no token, no network), turning a working shell call into
ready-to-paste SDK code:
asana-api --generate-python tasks get-task --task <TASK_GID>
# Generated equivalent (header and stdio-setup boilerplate trimmed):
import json
import os
import asana
configuration = asana.Configuration()
configuration.access_token = os.environ['ASANA_ACCESS_TOKEN']
api_client = asana.ApiClient(configuration)
api_instance = asana.TasksApi(api_client)
opts = {}
result = api_instance.get_task('<TASK_GID>', opts)
print(json.dumps(result, indent=2, ensure_ascii=False))
Redirect it to a file (asana-api … --generate-python > fetch_task.py) to keep
the script. It reproduces your configuration, output format, --query, --debug
(with the auth token masked), and uploads — see
Generating Python code
for the full behavior.
For the complete option reference — global options, pagination, output formats,
workspace resolution, error handling, and exit codes — see
docs/usage.md.
Asana only accepts Bearer-token authentication (personal access token, Service
Account, or OAuth), so authenticate with --access-token or
$ASANA_ACCESS_TOKEN.
Development
See docs/development.md for building from source and project layout.
License
Metadata
Release files for asana-api-cli 3.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| asana_api_cli-3.3.2.tar.gz | 288.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| asana_api_cli-3.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 357.1 kB
Release files / asana_api_cli-3.3.2.tar.gz
| Download URL | asana_api_cli-3.3.2.tar.gz |
|---|---|
| Size | 288.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ce9725e6ba7a973335092326ea6397ae2879b35bdd5691663c47030ed69873cb
|
|
BLAKE2b-256 checksum How to use checksums |
5b875d70fa5619ef648e46b63703004ab7f2bfe90bb249238470dafe77f92e1c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.
Transparency logRelease files / asana_api_cli-3.3.2-py3-none-any.whl
| Download URL | asana_api_cli-3.3.2-py3-none-any.whl |
|---|---|
| Size | 68.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
40921499b96b18fe1263856df2f2bf3c65b43ccfc23fceed076b756f553856ee
|
|
BLAKE2b-256 checksum How to use checksums |
087e5a67c0628791f29ed48373a7fdc90253c0600618f7e31d28b2cc5959cdf5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.
Transparency log