asana-api-cli 1.5.0__tar.gz → 2.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {asana_api_cli-1.5.0/src/asana_api_cli.egg-info → asana_api_cli-2.1.0}/PKG-INFO +111 -24
- asana_api_cli-2.1.0/README.md +245 -0
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/pyproject.toml +7 -7
- asana_api_cli-2.1.0/src/asana_api_cli/cli.py +674 -0
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/src/asana_api_cli/click_ext.py +5 -16
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/src/asana_api_cli/formatter.py +71 -19
- asana_api_cli-2.1.0/src/asana_api_cli/session.py +462 -0
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0/src/asana_api_cli.egg-info}/PKG-INFO +111 -24
- asana_api_cli-2.1.0/src/asana_api_cli.egg-info/SOURCES.txt +23 -0
- asana_api_cli-2.1.0/src/asana_api_cli.egg-info/requires.txt +4 -0
- asana_api_cli-2.1.0/tests/test_cli.py +292 -0
- asana_api_cli-2.1.0/tests/test_cli_invocation.py +527 -0
- asana_api_cli-2.1.0/tests/test_cli_surface.py +81 -0
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/tests/test_click_ext.py +1 -1
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/tests/test_formatter.py +149 -1
- asana_api_cli-2.1.0/tests/test_session.py +455 -0
- asana_api_cli-1.5.0/README.md +0 -158
- asana_api_cli-1.5.0/src/asana_api_cli/cli/__init__.py +0 -93
- asana_api_cli-1.5.0/src/asana_api_cli/cli/access_requests.py +0 -67
- asana_api_cli-1.5.0/src/asana_api_cli/cli/allocations.py +0 -112
- asana_api_cli-1.5.0/src/asana_api_cli/cli/attachments.py +0 -103
- asana_api_cli-1.5.0/src/asana_api_cli/cli/audit_log_api.py +0 -63
- asana_api_cli-1.5.0/src/asana_api_cli/cli/batch_api.py +0 -31
- asana_api_cli-1.5.0/src/asana_api_cli/cli/budgets.py +0 -80
- asana_api_cli-1.5.0/src/asana_api_cli/cli/custom_field_settings.py +0 -123
- asana_api_cli-1.5.0/src/asana_api_cli/cli/custom_fields.py +0 -144
- asana_api_cli-1.5.0/src/asana_api_cli/cli/custom_types.py +0 -61
- asana_api_cli-1.5.0/src/asana_api_cli/cli/events.py +0 -33
- asana_api_cli-1.5.0/src/asana_api_cli/cli/exports.py +0 -40
- asana_api_cli-1.5.0/src/asana_api_cli/cli/goal_relationships.py +0 -109
- asana_api_cli-1.5.0/src/asana_api_cli/cli/goals.py +0 -228
- asana_api_cli-1.5.0/src/asana_api_cli/cli/jobs.py +0 -30
- asana_api_cli-1.5.0/src/asana_api_cli/cli/memberships.py +0 -100
- asana_api_cli-1.5.0/src/asana_api_cli/cli/organization_exports.py +0 -45
- asana_api_cli-1.5.0/src/asana_api_cli/cli/portfolio_memberships.py +0 -104
- asana_api_cli-1.5.0/src/asana_api_cli/cli/portfolios.py +0 -236
- asana_api_cli-1.5.0/src/asana_api_cli/cli/project_briefs.py +0 -73
- asana_api_cli-1.5.0/src/asana_api_cli/cli/project_memberships.py +0 -64
- asana_api_cli-1.5.0/src/asana_api_cli/cli/project_portfolio_settings.py +0 -108
- asana_api_cli-1.5.0/src/asana_api_cli/cli/project_statuses.py +0 -88
- asana_api_cli-1.5.0/src/asana_api_cli/cli/project_templates.py +0 -123
- asana_api_cli-1.5.0/src/asana_api_cli/cli/projects.py +0 -421
- asana_api_cli-1.5.0/src/asana_api_cli/cli/rates.py +0 -108
- asana_api_cli-1.5.0/src/asana_api_cli/cli/reactions.py +0 -45
- asana_api_cli-1.5.0/src/asana_api_cli/cli/roles.py +0 -109
- asana_api_cli-1.5.0/src/asana_api_cli/cli/rules.py +0 -29
- asana_api_cli-1.5.0/src/asana_api_cli/cli/sections.py +0 -122
- asana_api_cli-1.5.0/src/asana_api_cli/cli/status_updates.py +0 -107
- asana_api_cli-1.5.0/src/asana_api_cli/cli/stories.py +0 -151
- asana_api_cli-1.5.0/src/asana_api_cli/cli/tags.py +0 -186
- asana_api_cli-1.5.0/src/asana_api_cli/cli/task_templates.py +0 -88
- asana_api_cli-1.5.0/src/asana_api_cli/cli/tasks.py +0 -601
- asana_api_cli-1.5.0/src/asana_api_cli/cli/team_memberships.py +0 -134
- asana_api_cli-1.5.0/src/asana_api_cli/cli/teams.py +0 -154
- asana_api_cli-1.5.0/src/asana_api_cli/cli/time_periods.py +0 -68
- asana_api_cli-1.5.0/src/asana_api_cli/cli/time_tracking_categories.py +0 -144
- asana_api_cli-1.5.0/src/asana_api_cli/cli/time_tracking_entries.py +0 -159
- asana_api_cli-1.5.0/src/asana_api_cli/cli/timesheet_approval_statuses.py +0 -105
- asana_api_cli-1.5.0/src/asana_api_cli/cli/typeahead.py +0 -41
- asana_api_cli-1.5.0/src/asana_api_cli/cli/user_task_lists.py +0 -46
- asana_api_cli-1.5.0/src/asana_api_cli/cli/users.py +0 -194
- asana_api_cli-1.5.0/src/asana_api_cli/cli/webhooks.py +0 -107
- asana_api_cli-1.5.0/src/asana_api_cli/cli/workspace_memberships.py +0 -96
- asana_api_cli-1.5.0/src/asana_api_cli/cli/workspaces.py +0 -124
- asana_api_cli-1.5.0/src/asana_api_cli/session.py +0 -222
- asana_api_cli-1.5.0/src/asana_api_cli.egg-info/SOURCES.txt +0 -67
- asana_api_cli-1.5.0/src/asana_api_cli.egg-info/requires.txt +0 -4
- asana_api_cli-1.5.0/tests/test_codegen.py +0 -290
- asana_api_cli-1.5.0/tests/test_session.py +0 -105
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/LICENSE +0 -0
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/setup.cfg +0 -0
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/src/asana_api_cli/__init__.py +0 -0
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/src/asana_api_cli/version.py +0 -0
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/src/asana_api_cli.egg-info/dependency_links.txt +0 -0
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/src/asana_api_cli.egg-info/entry_points.txt +0 -0
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/src/asana_api_cli.egg-info/top_level.txt +0 -0
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/tests/test_py310_compat.py +0 -0
- {asana_api_cli-1.5.0 → asana_api_cli-2.1.0}/tests/test_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: asana-api-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Command-line wrapper around the official Asana Python SDK
|
|
5
5
|
Author-email: Masanao Izumo <asana@masanao.site>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -11,43 +11,122 @@ Project-URL: Changelog, https://github.com/izumo-m/asana-api-cli/blob/main/CHANG
|
|
|
11
11
|
Requires-Python: >=3.10
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
|
-
Requires-Dist: click
|
|
15
|
-
Requires-Dist: jq
|
|
16
|
-
Requires-Dist: tabulate
|
|
17
|
-
Requires-Dist: asana<6,>=5.2
|
|
14
|
+
Requires-Dist: click>=8.0
|
|
15
|
+
Requires-Dist: jq>=1.6
|
|
16
|
+
Requires-Dist: tabulate>=0.9
|
|
17
|
+
Requires-Dist: asana<6,>=5.2
|
|
18
18
|
Dynamic: license-file
|
|
19
19
|
|
|
20
20
|
# asana-api-cli
|
|
21
21
|
|
|
22
|
-
A CLI
|
|
23
|
-
[python-asana](https://github.com/Asana/python-asana) SDK
|
|
24
|
-
|
|
22
|
+
A CLI that exposes **every method of the official
|
|
23
|
+
[`python-asana`](https://github.com/Asana/python-asana) SDK** as
|
|
24
|
+
`asana-api <group> <command>`. The command tree is generated at runtime
|
|
25
|
+
from the installed `asana` package, automatically tracking whatever
|
|
26
|
+
SDK version is installed in the same environment.
|
|
27
|
+
|
|
28
|
+
## Why asana-api-cli
|
|
29
|
+
|
|
30
|
+
- **Complete SDK coverage.** Every method of every `*Api` class in
|
|
31
|
+
`python-asana` becomes a CLI command. Because the tree is introspected
|
|
32
|
+
from the installed `asana` package, new methods surface the moment
|
|
33
|
+
upstream ships them — no `asana-api-cli` release required.
|
|
34
|
+
- **Tracks the SDK version you actually use.** Because commands are
|
|
35
|
+
introspected from whatever `asana` is installed in the same environment,
|
|
36
|
+
the CLI surface matches the SDK version pinned in your project. When using
|
|
37
|
+
`asana-api-cli` as a dev-dependency, `pip install -U asana` updates the
|
|
38
|
+
CLI's available commands in lockstep with your application code.
|
|
39
|
+
- **SDK-compatible arguments and output.** Command arguments map to
|
|
40
|
+
`python-asana` method parameters (with minor naming adjustments — hyphens
|
|
41
|
+
become underscores, group names map back to PascalCase `*Api` class
|
|
42
|
+
names), and JSON output matches the SDK's response shape. The CLI makes
|
|
43
|
+
it easy to iterate: try different arguments, inspect the response, and
|
|
44
|
+
refine until you understand the endpoint's behavior. Once verified,
|
|
45
|
+
translate the call into the equivalent `python-asana` invocation in your
|
|
46
|
+
app — far fewer surprises on the first integration.
|
|
25
47
|
|
|
26
48
|
## Installation
|
|
27
49
|
|
|
28
50
|
```bash
|
|
29
51
|
pip install asana-api-cli
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
For best results, install `asana-api-cli` into the same Python environment
|
|
55
|
+
that holds your project's `python-asana` so the CLI surface tracks the
|
|
56
|
+
exact SDK version your application uses (see [As a
|
|
57
|
+
dev-dependency](#as-a-dev-dependency) below).
|
|
58
|
+
|
|
59
|
+
### As a dev-dependency
|
|
60
|
+
|
|
61
|
+
If your project already uses `python-asana`, add `asana-api-cli` to your dev
|
|
62
|
+
group so the CLI tracks the same SDK version your application code uses:
|
|
63
|
+
|
|
64
|
+
```toml
|
|
65
|
+
# pyproject.toml
|
|
66
|
+
[project]
|
|
67
|
+
dependencies = ["asana>=5.2,<6"]
|
|
68
|
+
|
|
69
|
+
[dependency-groups] # uv
|
|
70
|
+
dev = ["asana-api-cli"]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```toml
|
|
74
|
+
# Poetry
|
|
75
|
+
[tool.poetry.group.dev.dependencies]
|
|
76
|
+
asana-api-cli = "*"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
After `uv sync` (or equivalent), `asana-api` resolves to the project's
|
|
80
|
+
`.venv` and introspects whatever `asana` version is locked there. Calls
|
|
81
|
+
prototyped with `asana-api tasks ...` translate directly to the SDK calls
|
|
82
|
+
you'll write in your app.
|
|
83
|
+
|
|
84
|
+
### Installing globally with pipx
|
|
85
|
+
|
|
86
|
+
If you would rather isolate `asana-api-cli` from any project's dependencies
|
|
87
|
+
— for example, when you administer Asana from the shell without writing
|
|
88
|
+
Python — install it with [pipx](https://pipx.pypa.io/):
|
|
30
89
|
|
|
31
|
-
|
|
90
|
+
```bash
|
|
32
91
|
pipx install asana-api-cli
|
|
33
92
|
```
|
|
34
93
|
|
|
94
|
+
In this setup the CLI uses the `python-asana` version pipx resolved when
|
|
95
|
+
installing `asana-api-cli`; `pipx upgrade asana-api-cli` updates only
|
|
96
|
+
`asana-api-cli` itself, not the bundled `python-asana`. To pull a newer
|
|
97
|
+
`python-asana` into the existing pipx install without reinstalling the
|
|
98
|
+
CLI:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
pipx runpip asana-api-cli install -U asana
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The next `asana-api` run sees the new SDK and any newly added methods
|
|
105
|
+
automatically.
|
|
106
|
+
|
|
35
107
|
## Environment variables
|
|
36
108
|
|
|
37
109
|
| Name | Required | Description |
|
|
38
110
|
|------|----------|-------------|
|
|
39
|
-
| `ASANA_ACCESS_TOKEN` | Yes (at runtime only) | Asana
|
|
111
|
+
| `ASANA_ACCESS_TOKEN` | Yes (at runtime only) | Asana personal access token |
|
|
40
112
|
| `ASANA_DEFAULT_WORKSPACE` | No | Default workspace GID for endpoints that require it |
|
|
41
113
|
|
|
42
114
|
The token can be issued from the
|
|
43
115
|
[Asana Developer Console](https://app.asana.com/0/developer-console).
|
|
44
|
-
No token is needed for `--help` or argument
|
|
116
|
+
No token is needed for `--help` or argument validation errors.
|
|
45
117
|
|
|
46
118
|
```bash
|
|
47
119
|
export ASANA_ACCESS_TOKEN="1/12345..."
|
|
48
120
|
export ASANA_DEFAULT_WORKSPACE="12345678" # optional
|
|
49
121
|
```
|
|
50
122
|
|
|
123
|
+
On Windows PowerShell:
|
|
124
|
+
|
|
125
|
+
```powershell
|
|
126
|
+
$env:ASANA_ACCESS_TOKEN = "1/12345..."
|
|
127
|
+
$env:ASANA_DEFAULT_WORKSPACE = "12345678" # optional
|
|
128
|
+
```
|
|
129
|
+
|
|
51
130
|
## Shell completion
|
|
52
131
|
|
|
53
132
|
`asana-api` is built with Click, which supports dynamic shell completion.
|
|
@@ -63,6 +142,9 @@ Then reload the shell (`source ~/.bashrc` or open a new terminal). Pressing
|
|
|
63
142
|
For `zsh` or `fish`, replace `bash_source` with `zsh_source` or `fish_source`
|
|
64
143
|
and add the line to `~/.zshrc` or `~/.config/fish/config.fish` respectively.
|
|
65
144
|
|
|
145
|
+
Click does not generate PowerShell completion. Windows users can install
|
|
146
|
+
completion under WSL or Git Bash using the `bash_source` line above.
|
|
147
|
+
|
|
66
148
|
## Usage
|
|
67
149
|
|
|
68
150
|
```bash
|
|
@@ -92,9 +174,14 @@ asana-api tasks get-task --task <TASK_GID>
|
|
|
92
174
|
# Create a task (body is a JSON string)
|
|
93
175
|
asana-api tasks create-task --body '{"data":{"name":"new task","projects":["<PID>"]}}'
|
|
94
176
|
|
|
95
|
-
# Output formats
|
|
96
|
-
|
|
177
|
+
# Output formats — pair non-JSON formats with `--query '.data'` to unwrap the
|
|
178
|
+
# `{"data": [...]}` envelope into one row per item.
|
|
179
|
+
asana-api tasks get-tasks --project <PID> --query '.data' --output table
|
|
97
180
|
asana-api tasks get-tasks --project <PID> --query '.data' --output csv
|
|
181
|
+
|
|
182
|
+
# CSV output is UTF-8 without a BOM by default. Pass --csv-bom for Excel on
|
|
183
|
+
# Windows, which otherwise displays non-ASCII characters as garbled text.
|
|
184
|
+
asana-api tasks get-tasks --project <PID> --output csv --csv-bom > tasks.csv
|
|
98
185
|
```
|
|
99
186
|
|
|
100
187
|
See [Pagination](#pagination) for fetching across pages and
|
|
@@ -102,20 +189,21 @@ See [Pagination](#pagination) for fetching across pages and
|
|
|
102
189
|
|
|
103
190
|
### Workspace resolution
|
|
104
191
|
|
|
105
|
-
Many API endpoints require a workspace. For
|
|
106
|
-
`get-projects-for-workspace`), the CLI resolves it in
|
|
192
|
+
Many API endpoints require a workspace. For commands wrapping such
|
|
193
|
+
endpoints (e.g. `get-projects-for-workspace`), the CLI resolves it in
|
|
194
|
+
this order:
|
|
107
195
|
|
|
108
196
|
1. `--workspace <GID>` on the command
|
|
109
197
|
2. `ASANA_DEFAULT_WORKSPACE` environment variable
|
|
110
198
|
|
|
111
|
-
For
|
|
199
|
+
For commands where workspace is optional (e.g. `get-tasks`), the env-var
|
|
112
200
|
fallback is **not** used — pass `--workspace` explicitly if needed. This
|
|
113
|
-
|
|
114
|
-
|
|
201
|
+
avoids ambiguity with alternative scope parameters like `--project` that
|
|
202
|
+
the Asana API accepts in place of workspace.
|
|
115
203
|
|
|
116
204
|
## Pagination
|
|
117
205
|
|
|
118
|
-
|
|
206
|
+
List commands (e.g. `tasks get-tasks`) return paginated results. The CLI
|
|
119
207
|
provides four ways to control how much is fetched:
|
|
120
208
|
|
|
121
209
|
| Option | Behavior |
|
|
@@ -129,7 +217,7 @@ provides four ways to control how much is fetched:
|
|
|
129
217
|
|
|
130
218
|
`--page-size N` tunes the per-page request size (Asana API requires 1-100,
|
|
131
219
|
default 100). Rarely needed — combine with `--all-items` or `--max-items` only
|
|
132
|
-
when the default doesn't suit (e.g. very large
|
|
220
|
+
when the default doesn't suit (e.g. very large response items).
|
|
133
221
|
|
|
134
222
|
```bash
|
|
135
223
|
# Auto-paginate up to 250 items
|
|
@@ -152,8 +240,7 @@ asana-api --debug tasks get-tasks --project <PID>
|
|
|
152
240
|
asana-api tasks get-tasks --project <PID> --debug
|
|
153
241
|
```
|
|
154
242
|
|
|
155
|
-
When the same option is given at multiple levels, the
|
|
156
|
-
one wins.
|
|
243
|
+
When the same option is given at multiple levels, the later one wins.
|
|
157
244
|
|
|
158
245
|
| Option | Description |
|
|
159
246
|
|--------|-------------|
|
|
@@ -165,12 +252,12 @@ one wins.
|
|
|
165
252
|
| `--retries N` | Number of retries on 429/5xx responses (default: 5) |
|
|
166
253
|
| `--timeout SECONDS` | Per-request timeout in seconds |
|
|
167
254
|
| `--temp-dir PATH` | Directory for temporary downloads |
|
|
168
|
-
| `--debug` | Print HTTP request/response
|
|
255
|
+
| `--debug` | Print HTTP request/response traces for troubleshooting (Authorization values are masked). |
|
|
169
256
|
|
|
170
257
|
## Development
|
|
171
258
|
|
|
172
259
|
See [docs/development.md](https://github.com/izumo-m/asana-api-cli/blob/main/docs/development.md)
|
|
173
|
-
for building from source
|
|
260
|
+
for building from source and project layout.
|
|
174
261
|
|
|
175
262
|
## License
|
|
176
263
|
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# asana-api-cli
|
|
2
|
+
|
|
3
|
+
A CLI that exposes **every method of the official
|
|
4
|
+
[`python-asana`](https://github.com/Asana/python-asana) SDK** as
|
|
5
|
+
`asana-api <group> <command>`. The command tree is generated at runtime
|
|
6
|
+
from the installed `asana` package, automatically tracking whatever
|
|
7
|
+
SDK version is installed in the same environment.
|
|
8
|
+
|
|
9
|
+
## Why asana-api-cli
|
|
10
|
+
|
|
11
|
+
- **Complete SDK coverage.** Every method of every `*Api` class in
|
|
12
|
+
`python-asana` becomes a CLI command. Because the tree is introspected
|
|
13
|
+
from the installed `asana` package, new methods surface the moment
|
|
14
|
+
upstream ships them — no `asana-api-cli` release required.
|
|
15
|
+
- **Tracks the SDK version you actually use.** Because commands are
|
|
16
|
+
introspected from whatever `asana` is installed in the same environment,
|
|
17
|
+
the CLI surface matches the SDK version pinned in your project. When using
|
|
18
|
+
`asana-api-cli` as a dev-dependency, `pip install -U asana` updates the
|
|
19
|
+
CLI's available commands in lockstep with your application code.
|
|
20
|
+
- **SDK-compatible arguments and output.** Command arguments map to
|
|
21
|
+
`python-asana` method parameters (with minor naming adjustments — hyphens
|
|
22
|
+
become underscores, group names map back to PascalCase `*Api` class
|
|
23
|
+
names), and JSON output matches the SDK's response shape. The CLI makes
|
|
24
|
+
it easy to iterate: try different arguments, inspect the response, and
|
|
25
|
+
refine until you understand the endpoint's behavior. Once verified,
|
|
26
|
+
translate the call into the equivalent `python-asana` invocation in your
|
|
27
|
+
app — far fewer surprises on the first integration.
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install asana-api-cli
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
For best results, install `asana-api-cli` into the same Python environment
|
|
36
|
+
that holds your project's `python-asana` so the CLI surface tracks the
|
|
37
|
+
exact SDK version your application uses (see [As a
|
|
38
|
+
dev-dependency](#as-a-dev-dependency) below).
|
|
39
|
+
|
|
40
|
+
### As a dev-dependency
|
|
41
|
+
|
|
42
|
+
If your project already uses `python-asana`, add `asana-api-cli` to your dev
|
|
43
|
+
group so the CLI tracks the same SDK version your application code uses:
|
|
44
|
+
|
|
45
|
+
```toml
|
|
46
|
+
# pyproject.toml
|
|
47
|
+
[project]
|
|
48
|
+
dependencies = ["asana>=5.2,<6"]
|
|
49
|
+
|
|
50
|
+
[dependency-groups] # uv
|
|
51
|
+
dev = ["asana-api-cli"]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```toml
|
|
55
|
+
# Poetry
|
|
56
|
+
[tool.poetry.group.dev.dependencies]
|
|
57
|
+
asana-api-cli = "*"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
After `uv sync` (or equivalent), `asana-api` resolves to the project's
|
|
61
|
+
`.venv` and introspects whatever `asana` version is locked there. Calls
|
|
62
|
+
prototyped with `asana-api tasks ...` translate directly to the SDK calls
|
|
63
|
+
you'll write in your app.
|
|
64
|
+
|
|
65
|
+
### Installing globally with pipx
|
|
66
|
+
|
|
67
|
+
If you would rather isolate `asana-api-cli` from any project's dependencies
|
|
68
|
+
— for example, when you administer Asana from the shell without writing
|
|
69
|
+
Python — install it with [pipx](https://pipx.pypa.io/):
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pipx install asana-api-cli
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
In this setup the CLI uses the `python-asana` version pipx resolved when
|
|
76
|
+
installing `asana-api-cli`; `pipx upgrade asana-api-cli` updates only
|
|
77
|
+
`asana-api-cli` itself, not the bundled `python-asana`. To pull a newer
|
|
78
|
+
`python-asana` into the existing pipx install without reinstalling the
|
|
79
|
+
CLI:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pipx runpip asana-api-cli install -U asana
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The next `asana-api` run sees the new SDK and any newly added methods
|
|
86
|
+
automatically.
|
|
87
|
+
|
|
88
|
+
## Environment variables
|
|
89
|
+
|
|
90
|
+
| Name | Required | Description |
|
|
91
|
+
|------|----------|-------------|
|
|
92
|
+
| `ASANA_ACCESS_TOKEN` | Yes (at runtime only) | Asana personal access token |
|
|
93
|
+
| `ASANA_DEFAULT_WORKSPACE` | No | Default workspace GID for endpoints that require it |
|
|
94
|
+
|
|
95
|
+
The token can be issued from the
|
|
96
|
+
[Asana Developer Console](https://app.asana.com/0/developer-console).
|
|
97
|
+
No token is needed for `--help` or argument validation errors.
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
export ASANA_ACCESS_TOKEN="1/12345..."
|
|
101
|
+
export ASANA_DEFAULT_WORKSPACE="12345678" # optional
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
On Windows PowerShell:
|
|
105
|
+
|
|
106
|
+
```powershell
|
|
107
|
+
$env:ASANA_ACCESS_TOKEN = "1/12345..."
|
|
108
|
+
$env:ASANA_DEFAULT_WORKSPACE = "12345678" # optional
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Shell completion
|
|
112
|
+
|
|
113
|
+
`asana-api` is built with Click, which supports dynamic shell completion.
|
|
114
|
+
To enable bash completion, add the following line to your `~/.bashrc`:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
eval "$(_ASANA_API_COMPLETE=bash_source asana-api)"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Then reload the shell (`source ~/.bashrc` or open a new terminal). Pressing
|
|
121
|
+
`<TAB>` after `asana-api` will now complete subcommands and options.
|
|
122
|
+
|
|
123
|
+
For `zsh` or `fish`, replace `bash_source` with `zsh_source` or `fish_source`
|
|
124
|
+
and add the line to `~/.zshrc` or `~/.config/fish/config.fish` respectively.
|
|
125
|
+
|
|
126
|
+
Click does not generate PowerShell completion. Windows users can install
|
|
127
|
+
completion under WSL or Git Bash using the `bash_source` line above.
|
|
128
|
+
|
|
129
|
+
## Usage
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Version and help
|
|
133
|
+
asana-api --version
|
|
134
|
+
asana-api --help
|
|
135
|
+
asana-api tasks --help
|
|
136
|
+
asana-api tasks get-tasks --help
|
|
137
|
+
|
|
138
|
+
# List workspaces and projects
|
|
139
|
+
asana-api workspaces get-workspaces
|
|
140
|
+
asana-api projects get-projects-for-workspace
|
|
141
|
+
asana-api projects get-projects --workspace <WORKSPACE_GID>
|
|
142
|
+
|
|
143
|
+
# List tasks (first page only by default)
|
|
144
|
+
asana-api tasks get-tasks --project <PROJECT_GID>
|
|
145
|
+
|
|
146
|
+
# Preview the first few items
|
|
147
|
+
asana-api tasks get-tasks --project <PROJECT_GID> --max-items 5
|
|
148
|
+
|
|
149
|
+
# Fetch every item across pages
|
|
150
|
+
asana-api tasks get-tasks --project <PROJECT_GID> --all-items
|
|
151
|
+
|
|
152
|
+
# Single task
|
|
153
|
+
asana-api tasks get-task --task <TASK_GID>
|
|
154
|
+
|
|
155
|
+
# Create a task (body is a JSON string)
|
|
156
|
+
asana-api tasks create-task --body '{"data":{"name":"new task","projects":["<PID>"]}}'
|
|
157
|
+
|
|
158
|
+
# Output formats — pair non-JSON formats with `--query '.data'` to unwrap the
|
|
159
|
+
# `{"data": [...]}` envelope into one row per item.
|
|
160
|
+
asana-api tasks get-tasks --project <PID> --query '.data' --output table
|
|
161
|
+
asana-api tasks get-tasks --project <PID> --query '.data' --output csv
|
|
162
|
+
|
|
163
|
+
# CSV output is UTF-8 without a BOM by default. Pass --csv-bom for Excel on
|
|
164
|
+
# Windows, which otherwise displays non-ASCII characters as garbled text.
|
|
165
|
+
asana-api tasks get-tasks --project <PID> --output csv --csv-bom > tasks.csv
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
See [Pagination](#pagination) for fetching across pages and
|
|
169
|
+
[Global options](#global-options) for `--debug`, `--access-token`, etc.
|
|
170
|
+
|
|
171
|
+
### Workspace resolution
|
|
172
|
+
|
|
173
|
+
Many API endpoints require a workspace. For commands wrapping such
|
|
174
|
+
endpoints (e.g. `get-projects-for-workspace`), the CLI resolves it in
|
|
175
|
+
this order:
|
|
176
|
+
|
|
177
|
+
1. `--workspace <GID>` on the command
|
|
178
|
+
2. `ASANA_DEFAULT_WORKSPACE` environment variable
|
|
179
|
+
|
|
180
|
+
For commands where workspace is optional (e.g. `get-tasks`), the env-var
|
|
181
|
+
fallback is **not** used — pass `--workspace` explicitly if needed. This
|
|
182
|
+
avoids ambiguity with alternative scope parameters like `--project` that
|
|
183
|
+
the Asana API accepts in place of workspace.
|
|
184
|
+
|
|
185
|
+
## Pagination
|
|
186
|
+
|
|
187
|
+
List commands (e.g. `tasks get-tasks`) return paginated results. The CLI
|
|
188
|
+
provides four ways to control how much is fetched:
|
|
189
|
+
|
|
190
|
+
| Option | Behavior |
|
|
191
|
+
|--------|----------|
|
|
192
|
+
| (none) | Fetch a single page (Asana default: 100 items) |
|
|
193
|
+
| `--max-items N` | Fetch up to N items, auto-paginating across pages. The last request is automatically capped to the remaining count. |
|
|
194
|
+
| `--all-items` | Fetch every page until the server reports no more |
|
|
195
|
+
| `--offset <TOKEN>` | Manual pagination: pass the `next_page.offset` token from the previous response |
|
|
196
|
+
|
|
197
|
+
`--max-items` and `--all-items` are mutually exclusive.
|
|
198
|
+
|
|
199
|
+
`--page-size N` tunes the per-page request size (Asana API requires 1-100,
|
|
200
|
+
default 100). Rarely needed — combine with `--all-items` or `--max-items` only
|
|
201
|
+
when the default doesn't suit (e.g. very large response items).
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
# Auto-paginate up to 250 items
|
|
205
|
+
asana-api tasks get-tasks --project <PID> --max-items 250
|
|
206
|
+
|
|
207
|
+
# Fetch everything
|
|
208
|
+
asana-api tasks get-tasks --project <PID> --all-items
|
|
209
|
+
|
|
210
|
+
# Manual pagination using the offset token
|
|
211
|
+
asana-api tasks get-tasks --project <PID> --offset <TOKEN>
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Global options
|
|
215
|
+
|
|
216
|
+
These options work at any level of the command tree, so the following are
|
|
217
|
+
equivalent:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
asana-api --debug tasks get-tasks --project <PID>
|
|
221
|
+
asana-api tasks get-tasks --project <PID> --debug
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
When the same option is given at multiple levels, the later one wins.
|
|
225
|
+
|
|
226
|
+
| Option | Description |
|
|
227
|
+
|--------|-------------|
|
|
228
|
+
| `--access-token TOKEN` | Asana personal access token (default: `$ASANA_ACCESS_TOKEN`) |
|
|
229
|
+
| `--host URL` | Override API base URL (default: `https://app.asana.com/api/1.0`) |
|
|
230
|
+
| `--proxy URL` | HTTP/HTTPS proxy URL |
|
|
231
|
+
| `--no-verify-ssl` | Disable TLS certificate verification (insecure) |
|
|
232
|
+
| `--ca-cert PATH` | Path to a PEM bundle of trusted CA certificates |
|
|
233
|
+
| `--retries N` | Number of retries on 429/5xx responses (default: 5) |
|
|
234
|
+
| `--timeout SECONDS` | Per-request timeout in seconds |
|
|
235
|
+
| `--temp-dir PATH` | Directory for temporary downloads |
|
|
236
|
+
| `--debug` | Print HTTP request/response traces for troubleshooting (Authorization values are masked). |
|
|
237
|
+
|
|
238
|
+
## Development
|
|
239
|
+
|
|
240
|
+
See [docs/development.md](https://github.com/izumo-m/asana-api-cli/blob/main/docs/development.md)
|
|
241
|
+
for building from source and project layout.
|
|
242
|
+
|
|
243
|
+
## License
|
|
244
|
+
|
|
245
|
+
[MIT License](https://github.com/izumo-m/asana-api-cli/blob/main/LICENSE)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "asana-api-cli"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "2.1.0"
|
|
4
4
|
description = "Command-line wrapper around the official Asana Python SDK"
|
|
5
5
|
authors = [{name = "Masanao Izumo", email = "asana@masanao.site"}]
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
license = "MIT"
|
|
8
8
|
requires-python = ">=3.10"
|
|
9
9
|
dependencies = [
|
|
10
|
-
"click>=8.
|
|
11
|
-
"jq>=1.
|
|
12
|
-
"tabulate>=0.9
|
|
13
|
-
"asana>=5.2
|
|
10
|
+
"click>=8.0",
|
|
11
|
+
"jq>=1.6",
|
|
12
|
+
"tabulate>=0.9",
|
|
13
|
+
"asana>=5.2,<6",
|
|
14
14
|
]
|
|
15
15
|
|
|
16
16
|
[project.urls]
|
|
@@ -24,7 +24,8 @@ asana-api = "asana_api_cli.cli:main"
|
|
|
24
24
|
|
|
25
25
|
[dependency-groups]
|
|
26
26
|
dev = [
|
|
27
|
-
"ruff
|
|
27
|
+
"ruff>=0.6",
|
|
28
|
+
"basedpyright>=1.13",
|
|
28
29
|
"pytest>=9,<10",
|
|
29
30
|
"build>=1,<2",
|
|
30
31
|
"twine>=6,<7",
|
|
@@ -41,7 +42,6 @@ where = ["src"]
|
|
|
41
42
|
[tool.ruff]
|
|
42
43
|
target-version = "py310"
|
|
43
44
|
line-length = 100
|
|
44
|
-
extend-exclude = ["src/asana_api_cli/cli"] # auto-generated (tools/codegen.py)
|
|
45
45
|
|
|
46
46
|
[tool.ruff.format]
|
|
47
47
|
docstring-code-format = true
|