atlassian-cli 0.3.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.
- atlassian_cli-0.3.0/LICENSE +21 -0
- atlassian_cli-0.3.0/PKG-INFO +235 -0
- atlassian_cli-0.3.0/README.md +205 -0
- atlassian_cli-0.3.0/pyproject.toml +59 -0
- atlassian_cli-0.3.0/setup.cfg +4 -0
- atlassian_cli-0.3.0/src/atlassian_cli/__init__.py +3 -0
- atlassian_cli-0.3.0/src/atlassian_cli/config.py +57 -0
- atlassian_cli-0.3.0/src/atlassian_cli/conflu.py +408 -0
- atlassian_cli-0.3.0/src/atlassian_cli/http.py +35 -0
- atlassian_cli-0.3.0/src/atlassian_cli/jira.py +149 -0
- atlassian_cli-0.3.0/src/atlassian_cli/jira_assets.py +167 -0
- atlassian_cli-0.3.0/src/atlassian_cli/jira_issues.py +147 -0
- atlassian_cli-0.3.0/src/atlassian_cli/output.py +28 -0
- atlassian_cli-0.3.0/src/atlassian_cli.egg-info/PKG-INFO +235 -0
- atlassian_cli-0.3.0/src/atlassian_cli.egg-info/SOURCES.txt +23 -0
- atlassian_cli-0.3.0/src/atlassian_cli.egg-info/dependency_links.txt +1 -0
- atlassian_cli-0.3.0/src/atlassian_cli.egg-info/entry_points.txt +3 -0
- atlassian_cli-0.3.0/src/atlassian_cli.egg-info/requires.txt +6 -0
- atlassian_cli-0.3.0/src/atlassian_cli.egg-info/top_level.txt +1 -0
- atlassian_cli-0.3.0/tests/test_config.py +93 -0
- atlassian_cli-0.3.0/tests/test_conflu.py +242 -0
- atlassian_cli-0.3.0/tests/test_http.py +90 -0
- atlassian_cli-0.3.0/tests/test_jira_assets.py +218 -0
- atlassian_cli-0.3.0/tests/test_jira_issues.py +225 -0
- atlassian_cli-0.3.0/tests/test_output.py +50 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Catapult CX
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: atlassian-cli
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Fast CLI tools for Atlassian Cloud (Confluence + Jira) — optimized for AI agents
|
|
5
|
+
Author-email: Alex Fishlock <alex.fishlock@catapult.cx>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/catapultcx/atlassian-cli
|
|
8
|
+
Project-URL: Repository, https://github.com/catapultcx/atlassian-cli
|
|
9
|
+
Project-URL: Issues, https://github.com/catapultcx/atlassian-cli/issues
|
|
10
|
+
Keywords: atlassian,confluence,jira,cli,claude,ai
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: requests>=2.28.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
27
|
+
Requires-Dist: responses>=0.23.0; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff>=0.4.0; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
<p align="center">
|
|
32
|
+
<h1 align="center">atlassian-cli</h1>
|
|
33
|
+
<p align="center">
|
|
34
|
+
Fast CLI tools for Atlassian Cloud — built for AI agents, loved by humans.
|
|
35
|
+
</p>
|
|
36
|
+
</p>
|
|
37
|
+
|
|
38
|
+
<p align="center">
|
|
39
|
+
<a href="https://github.com/catapultcx/atlassian-cli/actions/workflows/ci.yml"><img src="https://github.com/catapultcx/atlassian-cli/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
40
|
+
<a href="https://pypi.org/project/atlassian-cli/"><img src="https://img.shields.io/pypi/v/atlassian-cli" alt="PyPI"></a>
|
|
41
|
+
<a href="https://pypi.org/project/atlassian-cli/"><img src="https://img.shields.io/pypi/pyversions/atlassian-cli" alt="Python"></a>
|
|
42
|
+
<a href="https://github.com/catapultcx/atlassian-cli/blob/main/LICENSE"><img src="https://img.shields.io/github/license/catapultcx/atlassian-cli" alt="License"></a>
|
|
43
|
+
</p>
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
Two CLI tools — `confluence` and `jira` — that talk directly to Atlassian Cloud REST APIs. Zero bloat, one dependency (`requests`), deterministic output that AI agents parse in a single shot.
|
|
48
|
+
|
|
49
|
+
## Install
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install atlassian-cli
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Or from source:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install git+https://github.com/catapultcx/atlassian-cli.git
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Setup
|
|
62
|
+
|
|
63
|
+
Create a `.env` file (or export environment variables):
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
ATLASSIAN_URL=https://your-site.atlassian.net
|
|
67
|
+
ATLASSIAN_EMAIL=you@example.com
|
|
68
|
+
ATLASSIAN_TOKEN=your-api-token
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Get your API token at https://id.atlassian.com/manage-profile/security/api-tokens
|
|
72
|
+
|
|
73
|
+
> Legacy `CONFLUENCE_URL` / `CONFLUENCE_EMAIL` / `CONFLUENCE_TOKEN` env vars are also supported.
|
|
74
|
+
|
|
75
|
+
## Confluence CLI
|
|
76
|
+
|
|
77
|
+
Manages Confluence pages as local JSON files in ADF (Atlassian Document Format). No markdown — ADF preserves every macro, panel, and table perfectly.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Download a page
|
|
81
|
+
confluence get 9268920323
|
|
82
|
+
|
|
83
|
+
# Upload local edits back
|
|
84
|
+
confluence put 9268920323
|
|
85
|
+
confluence put 9268920323 --force # skip version check
|
|
86
|
+
|
|
87
|
+
# Compare local vs remote
|
|
88
|
+
confluence diff 9268920323
|
|
89
|
+
|
|
90
|
+
# Bulk-download an entire space (parallel, version-cached)
|
|
91
|
+
confluence sync POL
|
|
92
|
+
confluence sync COMPLY --workers 20 --force
|
|
93
|
+
|
|
94
|
+
# Search local page index (instant, no API call)
|
|
95
|
+
confluence search "risk assessment"
|
|
96
|
+
|
|
97
|
+
# Rebuild the page index
|
|
98
|
+
confluence index
|
|
99
|
+
confluence index --space POL --space COMPLY
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### How sync works
|
|
103
|
+
|
|
104
|
+
`sync` downloads every page in a space using parallel workers. It caches version numbers locally — subsequent syncs only fetch pages that changed. A full space of 500+ pages takes seconds.
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
pages/
|
|
108
|
+
POL/
|
|
109
|
+
9268920323.json # ADF body
|
|
110
|
+
9268920323.meta.json # title, version, timestamps
|
|
111
|
+
COMPLY/
|
|
112
|
+
5227515611.json
|
|
113
|
+
5227515611.meta.json
|
|
114
|
+
page-index.json # searchable index
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Jira CLI
|
|
118
|
+
|
|
119
|
+
### Issues
|
|
120
|
+
|
|
121
|
+
Full CRUD on Jira issues via REST API v3.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# Get issue details
|
|
125
|
+
jira issue get ISMS-42
|
|
126
|
+
|
|
127
|
+
# Create issues
|
|
128
|
+
jira issue create PROJ Task "Fix the login bug"
|
|
129
|
+
jira issue create PROJ Story "User auth" --description "As a user..." --labels security urgent
|
|
130
|
+
jira issue create PROJ Sub-task "Write tests" --parent PROJ-100
|
|
131
|
+
|
|
132
|
+
# Update fields
|
|
133
|
+
jira issue update ISMS-42 --summary "New title"
|
|
134
|
+
jira issue update ISMS-42 --labels risk compliance
|
|
135
|
+
jira issue update ISMS-42 --fields '{"priority": {"name": "High"}}'
|
|
136
|
+
|
|
137
|
+
# Delete
|
|
138
|
+
jira issue delete ISMS-42
|
|
139
|
+
|
|
140
|
+
# Search with JQL
|
|
141
|
+
jira issue search "project = ISMS AND status = Open"
|
|
142
|
+
jira issue search "assignee = currentUser() ORDER BY updated DESC" --max 20
|
|
143
|
+
|
|
144
|
+
# Transitions
|
|
145
|
+
jira issue transition ISMS-42 "In Progress"
|
|
146
|
+
jira issue transition ISMS-42 Done
|
|
147
|
+
|
|
148
|
+
# Comments
|
|
149
|
+
jira issue comment ISMS-42 "Fixed in v2.1"
|
|
150
|
+
jira issue comments ISMS-42
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Assets (JSM)
|
|
154
|
+
|
|
155
|
+
CRUD for Jira Service Management Assets via the Assets REST API v1.
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Browse schemas and types
|
|
159
|
+
jira assets schemas
|
|
160
|
+
jira assets schema 1
|
|
161
|
+
jira assets types 1
|
|
162
|
+
jira assets type 5
|
|
163
|
+
jira assets attrs 5
|
|
164
|
+
|
|
165
|
+
# Search with AQL
|
|
166
|
+
jira assets search "objectType = Server"
|
|
167
|
+
|
|
168
|
+
# CRUD objects
|
|
169
|
+
jira assets get 123
|
|
170
|
+
jira assets create 5 Name=srv01 IP=10.0.0.1
|
|
171
|
+
jira assets update 123 Name=srv02
|
|
172
|
+
jira assets delete 123
|
|
173
|
+
|
|
174
|
+
# Create new object types
|
|
175
|
+
jira assets type-create 1 "Network Device" --description "Switches and routers"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## `--json` flag
|
|
179
|
+
|
|
180
|
+
Both CLIs accept a global `--json` flag that switches all output to machine-readable JSON. Perfect for piping into `jq` or parsing from code.
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Text mode (default)
|
|
184
|
+
$ confluence get 9268920323
|
|
185
|
+
OK Artificial Intelligence Policy (v12) -> pages/POL/9268920323.json
|
|
186
|
+
|
|
187
|
+
# JSON mode
|
|
188
|
+
$ confluence --json get 9268920323
|
|
189
|
+
{"status":"ok","message":"Artificial Intelligence Policy (v12) -> pages/POL/9268920323.json"}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Output format
|
|
193
|
+
|
|
194
|
+
All commands emit status-prefixed lines for easy parsing:
|
|
195
|
+
|
|
196
|
+
| Prefix | Meaning |
|
|
197
|
+
|--------|---------|
|
|
198
|
+
| `OK` | Success |
|
|
199
|
+
| `GET` | Page downloaded |
|
|
200
|
+
| `SKIP` | Already up-to-date |
|
|
201
|
+
| `ERR` | Error |
|
|
202
|
+
| `DONE` | Batch complete |
|
|
203
|
+
|
|
204
|
+
## Architecture
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
src/atlassian_cli/
|
|
208
|
+
config.py Shared auth, .env parsing, session factory
|
|
209
|
+
http.py API helpers: get/post/put/delete + error handling
|
|
210
|
+
output.py Text & JSON output formatting
|
|
211
|
+
conflu.py Confluence CLI (v2 API, ADF)
|
|
212
|
+
jira.py Jira CLI entry point (subparsers)
|
|
213
|
+
jira_issues.py Jira issue commands (v3 API)
|
|
214
|
+
jira_assets.py Jira Assets commands (Assets v1 API)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**APIs used:**
|
|
218
|
+
- Confluence Cloud REST API v2 (`/wiki/api/v2/`)
|
|
219
|
+
- Jira Cloud REST API v3 (`/rest/api/3/`)
|
|
220
|
+
- Jira Assets REST API v1 (`api.atlassian.com/jsm/assets/workspace/{id}/v1`)
|
|
221
|
+
|
|
222
|
+
## Development
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
git clone https://github.com/catapultcx/atlassian-cli.git
|
|
226
|
+
cd atlassian-cli
|
|
227
|
+
python -m venv .venv && source .venv/bin/activate
|
|
228
|
+
pip install -e ".[dev]"
|
|
229
|
+
pytest
|
|
230
|
+
ruff check src/ tests/
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## License
|
|
234
|
+
|
|
235
|
+
MIT
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">atlassian-cli</h1>
|
|
3
|
+
<p align="center">
|
|
4
|
+
Fast CLI tools for Atlassian Cloud — built for AI agents, loved by humans.
|
|
5
|
+
</p>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a href="https://github.com/catapultcx/atlassian-cli/actions/workflows/ci.yml"><img src="https://github.com/catapultcx/atlassian-cli/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
10
|
+
<a href="https://pypi.org/project/atlassian-cli/"><img src="https://img.shields.io/pypi/v/atlassian-cli" alt="PyPI"></a>
|
|
11
|
+
<a href="https://pypi.org/project/atlassian-cli/"><img src="https://img.shields.io/pypi/pyversions/atlassian-cli" alt="Python"></a>
|
|
12
|
+
<a href="https://github.com/catapultcx/atlassian-cli/blob/main/LICENSE"><img src="https://img.shields.io/github/license/catapultcx/atlassian-cli" alt="License"></a>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
Two CLI tools — `confluence` and `jira` — that talk directly to Atlassian Cloud REST APIs. Zero bloat, one dependency (`requests`), deterministic output that AI agents parse in a single shot.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install atlassian-cli
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Or from source:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install git+https://github.com/catapultcx/atlassian-cli.git
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Setup
|
|
32
|
+
|
|
33
|
+
Create a `.env` file (or export environment variables):
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
ATLASSIAN_URL=https://your-site.atlassian.net
|
|
37
|
+
ATLASSIAN_EMAIL=you@example.com
|
|
38
|
+
ATLASSIAN_TOKEN=your-api-token
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Get your API token at https://id.atlassian.com/manage-profile/security/api-tokens
|
|
42
|
+
|
|
43
|
+
> Legacy `CONFLUENCE_URL` / `CONFLUENCE_EMAIL` / `CONFLUENCE_TOKEN` env vars are also supported.
|
|
44
|
+
|
|
45
|
+
## Confluence CLI
|
|
46
|
+
|
|
47
|
+
Manages Confluence pages as local JSON files in ADF (Atlassian Document Format). No markdown — ADF preserves every macro, panel, and table perfectly.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Download a page
|
|
51
|
+
confluence get 9268920323
|
|
52
|
+
|
|
53
|
+
# Upload local edits back
|
|
54
|
+
confluence put 9268920323
|
|
55
|
+
confluence put 9268920323 --force # skip version check
|
|
56
|
+
|
|
57
|
+
# Compare local vs remote
|
|
58
|
+
confluence diff 9268920323
|
|
59
|
+
|
|
60
|
+
# Bulk-download an entire space (parallel, version-cached)
|
|
61
|
+
confluence sync POL
|
|
62
|
+
confluence sync COMPLY --workers 20 --force
|
|
63
|
+
|
|
64
|
+
# Search local page index (instant, no API call)
|
|
65
|
+
confluence search "risk assessment"
|
|
66
|
+
|
|
67
|
+
# Rebuild the page index
|
|
68
|
+
confluence index
|
|
69
|
+
confluence index --space POL --space COMPLY
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### How sync works
|
|
73
|
+
|
|
74
|
+
`sync` downloads every page in a space using parallel workers. It caches version numbers locally — subsequent syncs only fetch pages that changed. A full space of 500+ pages takes seconds.
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
pages/
|
|
78
|
+
POL/
|
|
79
|
+
9268920323.json # ADF body
|
|
80
|
+
9268920323.meta.json # title, version, timestamps
|
|
81
|
+
COMPLY/
|
|
82
|
+
5227515611.json
|
|
83
|
+
5227515611.meta.json
|
|
84
|
+
page-index.json # searchable index
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Jira CLI
|
|
88
|
+
|
|
89
|
+
### Issues
|
|
90
|
+
|
|
91
|
+
Full CRUD on Jira issues via REST API v3.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Get issue details
|
|
95
|
+
jira issue get ISMS-42
|
|
96
|
+
|
|
97
|
+
# Create issues
|
|
98
|
+
jira issue create PROJ Task "Fix the login bug"
|
|
99
|
+
jira issue create PROJ Story "User auth" --description "As a user..." --labels security urgent
|
|
100
|
+
jira issue create PROJ Sub-task "Write tests" --parent PROJ-100
|
|
101
|
+
|
|
102
|
+
# Update fields
|
|
103
|
+
jira issue update ISMS-42 --summary "New title"
|
|
104
|
+
jira issue update ISMS-42 --labels risk compliance
|
|
105
|
+
jira issue update ISMS-42 --fields '{"priority": {"name": "High"}}'
|
|
106
|
+
|
|
107
|
+
# Delete
|
|
108
|
+
jira issue delete ISMS-42
|
|
109
|
+
|
|
110
|
+
# Search with JQL
|
|
111
|
+
jira issue search "project = ISMS AND status = Open"
|
|
112
|
+
jira issue search "assignee = currentUser() ORDER BY updated DESC" --max 20
|
|
113
|
+
|
|
114
|
+
# Transitions
|
|
115
|
+
jira issue transition ISMS-42 "In Progress"
|
|
116
|
+
jira issue transition ISMS-42 Done
|
|
117
|
+
|
|
118
|
+
# Comments
|
|
119
|
+
jira issue comment ISMS-42 "Fixed in v2.1"
|
|
120
|
+
jira issue comments ISMS-42
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Assets (JSM)
|
|
124
|
+
|
|
125
|
+
CRUD for Jira Service Management Assets via the Assets REST API v1.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# Browse schemas and types
|
|
129
|
+
jira assets schemas
|
|
130
|
+
jira assets schema 1
|
|
131
|
+
jira assets types 1
|
|
132
|
+
jira assets type 5
|
|
133
|
+
jira assets attrs 5
|
|
134
|
+
|
|
135
|
+
# Search with AQL
|
|
136
|
+
jira assets search "objectType = Server"
|
|
137
|
+
|
|
138
|
+
# CRUD objects
|
|
139
|
+
jira assets get 123
|
|
140
|
+
jira assets create 5 Name=srv01 IP=10.0.0.1
|
|
141
|
+
jira assets update 123 Name=srv02
|
|
142
|
+
jira assets delete 123
|
|
143
|
+
|
|
144
|
+
# Create new object types
|
|
145
|
+
jira assets type-create 1 "Network Device" --description "Switches and routers"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## `--json` flag
|
|
149
|
+
|
|
150
|
+
Both CLIs accept a global `--json` flag that switches all output to machine-readable JSON. Perfect for piping into `jq` or parsing from code.
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Text mode (default)
|
|
154
|
+
$ confluence get 9268920323
|
|
155
|
+
OK Artificial Intelligence Policy (v12) -> pages/POL/9268920323.json
|
|
156
|
+
|
|
157
|
+
# JSON mode
|
|
158
|
+
$ confluence --json get 9268920323
|
|
159
|
+
{"status":"ok","message":"Artificial Intelligence Policy (v12) -> pages/POL/9268920323.json"}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Output format
|
|
163
|
+
|
|
164
|
+
All commands emit status-prefixed lines for easy parsing:
|
|
165
|
+
|
|
166
|
+
| Prefix | Meaning |
|
|
167
|
+
|--------|---------|
|
|
168
|
+
| `OK` | Success |
|
|
169
|
+
| `GET` | Page downloaded |
|
|
170
|
+
| `SKIP` | Already up-to-date |
|
|
171
|
+
| `ERR` | Error |
|
|
172
|
+
| `DONE` | Batch complete |
|
|
173
|
+
|
|
174
|
+
## Architecture
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
src/atlassian_cli/
|
|
178
|
+
config.py Shared auth, .env parsing, session factory
|
|
179
|
+
http.py API helpers: get/post/put/delete + error handling
|
|
180
|
+
output.py Text & JSON output formatting
|
|
181
|
+
conflu.py Confluence CLI (v2 API, ADF)
|
|
182
|
+
jira.py Jira CLI entry point (subparsers)
|
|
183
|
+
jira_issues.py Jira issue commands (v3 API)
|
|
184
|
+
jira_assets.py Jira Assets commands (Assets v1 API)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**APIs used:**
|
|
188
|
+
- Confluence Cloud REST API v2 (`/wiki/api/v2/`)
|
|
189
|
+
- Jira Cloud REST API v3 (`/rest/api/3/`)
|
|
190
|
+
- Jira Assets REST API v1 (`api.atlassian.com/jsm/assets/workspace/{id}/v1`)
|
|
191
|
+
|
|
192
|
+
## Development
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
git clone https://github.com/catapultcx/atlassian-cli.git
|
|
196
|
+
cd atlassian-cli
|
|
197
|
+
python -m venv .venv && source .venv/bin/activate
|
|
198
|
+
pip install -e ".[dev]"
|
|
199
|
+
pytest
|
|
200
|
+
ruff check src/ tests/
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## License
|
|
204
|
+
|
|
205
|
+
MIT
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "atlassian-cli"
|
|
7
|
+
version = "0.3.0"
|
|
8
|
+
description = "Fast CLI tools for Atlassian Cloud (Confluence + Jira) — optimized for AI agents"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Alex Fishlock", email = "alex.fishlock@catapult.cx"},
|
|
14
|
+
]
|
|
15
|
+
keywords = ["atlassian", "confluence", "jira", "cli", "claude", "ai"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Topic :: Software Development :: Libraries",
|
|
26
|
+
"Topic :: Utilities",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"requests>=2.28.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = [
|
|
34
|
+
"pytest>=7.0",
|
|
35
|
+
"responses>=0.23.0",
|
|
36
|
+
"ruff>=0.4.0",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://github.com/catapultcx/atlassian-cli"
|
|
41
|
+
Repository = "https://github.com/catapultcx/atlassian-cli"
|
|
42
|
+
Issues = "https://github.com/catapultcx/atlassian-cli/issues"
|
|
43
|
+
|
|
44
|
+
[project.scripts]
|
|
45
|
+
confluence = "atlassian_cli.conflu:main"
|
|
46
|
+
jira = "atlassian_cli.jira:main"
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.packages.find]
|
|
49
|
+
where = ["src"]
|
|
50
|
+
|
|
51
|
+
[tool.pytest.ini_options]
|
|
52
|
+
testpaths = ["tests"]
|
|
53
|
+
|
|
54
|
+
[tool.ruff]
|
|
55
|
+
target-version = "py310"
|
|
56
|
+
line-length = 120
|
|
57
|
+
|
|
58
|
+
[tool.ruff.lint]
|
|
59
|
+
select = ["E", "F", "W", "I"]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Shared Atlassian Cloud configuration and session factory for atlassian_cli package."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
import requests
|
|
7
|
+
from requests.auth import HTTPBasicAuth
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def load_env(path=None):
|
|
11
|
+
"""Manually parse a .env file into a dict, skipping comments and blank lines."""
|
|
12
|
+
if path is None:
|
|
13
|
+
paths = [os.path.join(os.getcwd(), '.env'), os.path.join(os.path.dirname(__file__), '.env')]
|
|
14
|
+
else:
|
|
15
|
+
paths = [path]
|
|
16
|
+
|
|
17
|
+
for env_path in paths:
|
|
18
|
+
if os.path.exists(env_path):
|
|
19
|
+
with open(env_path, 'r') as file:
|
|
20
|
+
return dict(line.strip().split('=', 1) for line in file if not line.startswith('#') and '=' in line)
|
|
21
|
+
return {}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_config():
|
|
25
|
+
"""Return tuple (url, email, token) from .env or environment variables."""
|
|
26
|
+
env = load_env()
|
|
27
|
+
url = env.get('ATLASSIAN_URL', os.environ.get('ATLASSIAN_URL')) or \
|
|
28
|
+
env.get('CONFLUENCE_URL', os.environ.get('CONFLUENCE_URL'))
|
|
29
|
+
email = env.get('ATLASSIAN_EMAIL', os.environ.get('ATLASSIAN_EMAIL')) or \
|
|
30
|
+
env.get('CONFLUENCE_EMAIL', os.environ.get('CONFLUENCE_EMAIL'))
|
|
31
|
+
token = env.get('ATLASSIAN_TOKEN', os.environ.get('ATLASSIAN_TOKEN')) or \
|
|
32
|
+
env.get('CONFLUENCE_TOKEN', os.environ.get('CONFLUENCE_TOKEN'))
|
|
33
|
+
|
|
34
|
+
if not all([url, email, token]):
|
|
35
|
+
sys.stderr.write('ERR Missing ATLASSIAN_URL, ATLASSIAN_EMAIL, or ATLASSIAN_TOKEN\n'
|
|
36
|
+
'Set them in .env or as environment variables.\n')
|
|
37
|
+
sys.exit(1)
|
|
38
|
+
|
|
39
|
+
return url.rstrip('/'), email, token
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def get_session(email, token):
|
|
43
|
+
"""Create requests.Session with HTTPBasicAuth and JSON headers."""
|
|
44
|
+
session = requests.Session()
|
|
45
|
+
session.auth = HTTPBasicAuth(email, token)
|
|
46
|
+
session.headers.update({
|
|
47
|
+
'Accept': 'application/json',
|
|
48
|
+
'Content-Type': 'application/json'
|
|
49
|
+
})
|
|
50
|
+
return session
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def setup():
|
|
54
|
+
"""Setup configuration and session, returning (session, base_url)."""
|
|
55
|
+
url, email, token = get_config()
|
|
56
|
+
session = get_session(email, token)
|
|
57
|
+
return session, url
|