conjira-cli 0.2.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.
Files changed (31) hide show
  1. conjira_cli-0.2.0/LICENSE +21 -0
  2. conjira_cli-0.2.0/PKG-INFO +409 -0
  3. conjira_cli-0.2.0/README.md +380 -0
  4. conjira_cli-0.2.0/pyproject.toml +57 -0
  5. conjira_cli-0.2.0/setup.cfg +4 -0
  6. conjira_cli-0.2.0/setup.py +4 -0
  7. conjira_cli-0.2.0/src/conjira_cli/__init__.py +3 -0
  8. conjira_cli-0.2.0/src/conjira_cli/__main__.py +5 -0
  9. conjira_cli-0.2.0/src/conjira_cli/cli.py +1257 -0
  10. conjira_cli-0.2.0/src/conjira_cli/client.py +585 -0
  11. conjira_cli-0.2.0/src/conjira_cli/config.py +259 -0
  12. conjira_cli-0.2.0/src/conjira_cli/inline_comments.py +267 -0
  13. conjira_cli-0.2.0/src/conjira_cli/markdown_export.py +490 -0
  14. conjira_cli-0.2.0/src/conjira_cli/markdown_import.py +390 -0
  15. conjira_cli-0.2.0/src/conjira_cli/section_edit.py +124 -0
  16. conjira_cli-0.2.0/src/conjira_cli/setup_macos.py +220 -0
  17. conjira_cli-0.2.0/src/conjira_cli/tree_export.py +74 -0
  18. conjira_cli-0.2.0/src/conjira_cli.egg-info/PKG-INFO +409 -0
  19. conjira_cli-0.2.0/src/conjira_cli.egg-info/SOURCES.txt +29 -0
  20. conjira_cli-0.2.0/src/conjira_cli.egg-info/dependency_links.txt +1 -0
  21. conjira_cli-0.2.0/src/conjira_cli.egg-info/entry_points.txt +4 -0
  22. conjira_cli-0.2.0/src/conjira_cli.egg-info/top_level.txt +1 -0
  23. conjira_cli-0.2.0/tests/test_cli.py +741 -0
  24. conjira_cli-0.2.0/tests/test_client.py +152 -0
  25. conjira_cli-0.2.0/tests/test_config.py +105 -0
  26. conjira_cli-0.2.0/tests/test_inline_comments.py +100 -0
  27. conjira_cli-0.2.0/tests/test_markdown_export.py +122 -0
  28. conjira_cli-0.2.0/tests/test_markdown_import.py +61 -0
  29. conjira_cli-0.2.0/tests/test_section_edit.py +48 -0
  30. conjira_cli-0.2.0/tests/test_setup_macos.py +76 -0
  31. conjira_cli-0.2.0/tests/test_tree_export.py +56 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daehwan
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,409 @@
1
+ Metadata-Version: 2.4
2
+ Name: conjira-cli
3
+ Version: 0.2.0
4
+ Summary: Unofficial agent-friendly CLI for self-hosted Confluence and Jira
5
+ Author: quanttraderkim
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/quanttraderkim/conjira-cli
8
+ Project-URL: Repository, https://github.com/quanttraderkim/conjira-cli
9
+ Project-URL: Issues, https://github.com/quanttraderkim/conjira-cli/issues
10
+ Keywords: confluence,jira,atlassian,markdown,cli,mcp,agent
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: MacOS
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Topic :: Utilities
25
+ Requires-Python: >=3.9
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Dynamic: license-file
29
+
30
+ # conjira-cli
31
+
32
+ Unofficial, agent-friendly CLI for self-hosted Confluence and Jira.
33
+
34
+ Korean version: [README.ko.md](README.ko.md)
35
+
36
+ Release notes for maintainers: [docs/RELEASING.md](docs/RELEASING.md)
37
+
38
+ `conjira-cli` is a small Python command-line tool for teams that run Confluence and Jira on their own infrastructure and want a practical local interface for scripts, coding agents, and Markdown workflows. It wraps standard Atlassian REST APIs behind a simple CLI, supports safer local credential handling, and adds guardrails for write operations.
39
+
40
+ You do not need to be a Python developer to get value from this repository. If you already use a local coding agent or another shell-capable AI tool, you can hand the repo to the agent, point it at your local `agent.env`, and ask for tasks like “export this Confluence page to Markdown”, “refresh this stale wiki note”, or “search Jira for issues created this week”. The agent can read this README, follow `docs/AGENT_USAGE.md`, and run the CLI for you.
41
+
42
+ ## The problem this solves
43
+
44
+ If your team uses self-hosted Confluence and Jira, official cloud-native connectors are often not enough. You still have the REST APIs, but the missing piece is usually a reusable local tool that makes those APIs easy to use from a shell or from local coding agents.
45
+
46
+ `conjira-cli` is built for that gap. It helps when you want to read Confluence pages, export them to Markdown, refresh stale exports from the live wiki, summarize inline comment threads, search Jira with JQL, or create and update content without hardcoding PATs into source files or chat transcripts.
47
+
48
+ ## What you can do with it
49
+
50
+ - read Confluence pages and search with CQL
51
+ - export Confluence pages to Markdown for note systems, docs folders, or knowledge bases
52
+ - create or update Confluence pages from either storage HTML or Markdown
53
+ - detect stale Markdown exports and refresh them from the live page
54
+ - fetch and export grouped Confluence inline comment threads
55
+ - upload attachments to Confluence pages
56
+ - read Jira issues, search with JQL, inspect create metadata, create issues, and add comments
57
+ - preview writes with `--dry-run`, then enforce them with `--allow-write` plus optional allowlists
58
+
59
+ ## Who this is for
60
+
61
+ This tool is aimed at self-hosted Atlassian environments first, especially Server/Data Center style deployments. The current tested path uses Personal Access Tokens with Bearer auth against self-hosted base URLs, which matches the on-premise Atlassian pattern much better than Atlassian Cloud. Official references: [Atlassian Cloud basic auth](https://developer.atlassian.com/cloud/jira/service-desk/basic-auth-for-rest-apis/) and [Atlassian Personal Access Tokens](https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html).
62
+
63
+ ## Demo
64
+
65
+ Validate both products:
66
+
67
+ ```bash
68
+ ./bin/conjira --env-file ./local/agent.env auth-check
69
+ ./bin/conjira --env-file ./local/agent.env jira-auth-check
70
+ ```
71
+
72
+ Export a Confluence page to Markdown:
73
+
74
+ ```bash
75
+ ./bin/conjira --env-file ./local/agent.env export-page-md --page-id 123456 --output-dir "/path/to/notes"
76
+ ```
77
+
78
+ Create a Confluence page directly from Markdown:
79
+
80
+ ```bash
81
+ ./bin/conjira --env-file ./local/agent.env create-page --allow-write --space-key DOCS --parent-id 100001 --title "Markdown page" --body-markdown-file ./notes/demo.md
82
+ ```
83
+
84
+ Replace one section under a specific heading:
85
+
86
+ ```bash
87
+ ./bin/conjira --env-file ./local/agent.env replace-section --dry-run --page-id 123456 --heading "Rollout plan" --section-markdown-file ./notes/rollout.md
88
+ ```
89
+
90
+ Preview a write without changing anything:
91
+
92
+ ```bash
93
+ ./bin/conjira --env-file ./local/agent.env create-page --dry-run --space-key DOCS --parent-id 100001 --title "Preview only" --body-markdown "# Demo"
94
+ ./bin/conjira --env-file ./local/agent.env jira-add-comment --dry-run --issue-key DEMO-123 --body "Preview only"
95
+ ```
96
+
97
+ Check whether an exported file is stale and refresh it if the live page changed:
98
+
99
+ ```bash
100
+ ./bin/conjira --env-file ./local/agent.env check-page-md-freshness --file "/path/to/notes/page.md"
101
+ ./bin/conjira --env-file ./local/agent.env refresh-page-md --file "/path/to/notes/page.md"
102
+ ```
103
+
104
+ Summarize inline comment threads on a Confluence page:
105
+
106
+ ```bash
107
+ ./bin/conjira --env-file ./local/agent.env export-inline-comments-md --page-id 123456 --status open --output-dir "/path/to/notes"
108
+ ```
109
+
110
+ Search Jira and fetch an issue:
111
+
112
+ ```bash
113
+ ./bin/conjira --env-file ./local/agent.env jira-search --jql 'project = DEMO ORDER BY created DESC' --limit 5
114
+ ./bin/conjira --env-file ./local/agent.env jira-get-issue --issue-key DEMO-123
115
+ ```
116
+
117
+ Short sample output blocks, using synthetic values:
118
+
119
+ ```json
120
+ {
121
+ "base_url": "https://confluence.example.com",
122
+ "authenticated": true,
123
+ "space_count_sample": 1,
124
+ "first_space_key": "DOCS"
125
+ }
126
+ ```
127
+
128
+ ```json
129
+ {
130
+ "page_id": "123456",
131
+ "title": "Quarterly planning notes",
132
+ "output_file": "/path/to/notes/Quarterly planning notes.md",
133
+ "source_url": "https://confluence.example.com/pages/viewpage.action?pageId=123456",
134
+ "used_staging_local": false
135
+ }
136
+ ```
137
+
138
+ ```json
139
+ {
140
+ "key": "DEMO-123",
141
+ "summary": "Roll out the new onboarding flow",
142
+ "status": "In Progress",
143
+ "issue_type": "Task",
144
+ "assignee": "Alex Kim",
145
+ "browse_url": "https://jira.example.com/browse/DEMO-123"
146
+ }
147
+ ```
148
+
149
+ ## Set up in about 5 minutes
150
+
151
+ If you already use `pipx`, the shortest install path is:
152
+
153
+ ```bash
154
+ pipx install git+https://github.com/quanttraderkim/conjira-cli.git
155
+ conjira-setup-macos
156
+ ```
157
+
158
+ Or install from a local checkout:
159
+
160
+ ```bash
161
+ git clone https://github.com/quanttraderkim/conjira-cli.git
162
+ cd conjira-cli
163
+ python3 -m venv .venv
164
+ source .venv/bin/activate
165
+ python -m pip install --upgrade pip setuptools wheel
166
+ pip install -e .
167
+ ```
168
+
169
+ If you do not want to install the package yet, the checked-in wrappers work directly:
170
+
171
+ ```bash
172
+ ./bin/conjira --help
173
+ ./bin/conjira-cli --help
174
+ ```
175
+
176
+ Create a local config file:
177
+
178
+ ```bash
179
+ cp ./local/agent.env.example ./local/agent.env
180
+ ```
181
+
182
+ On macOS, you can do the first-time Keychain-based setup with one script instead of editing `local/agent.env` by hand:
183
+
184
+ ```bash
185
+ conjira-setup-macos
186
+ ```
187
+
188
+ The script stores PATs in macOS Keychain, writes only non-secret settings to `local/agent.env`, and can run `auth-check` for you at the end.
189
+ It does not write PAT values to `~/.zshrc` or other shell profile files.
190
+ If you are running directly from a source checkout before installing entrypoints, you can still use:
191
+
192
+ ```bash
193
+ bash scripts/setup-conjira-macos.sh
194
+ ```
195
+
196
+ ## Credential handling
197
+
198
+ The recommended setup depends on your OS.
199
+
200
+ On macOS, the best local experience is to keep PATs in Keychain and store only non-secret machine settings in `local/agent.env`.
201
+
202
+ If you want the easiest path on macOS, run:
203
+
204
+ ```bash
205
+ conjira-setup-macos
206
+ ```
207
+
208
+ If you prefer to set everything manually, use the Keychain flow below.
209
+
210
+ ```dotenv
211
+ CONFLUENCE_BASE_URL=https://confluence.example.com
212
+ CONFLUENCE_PAT_KEYCHAIN_SERVICE=conjira-cli
213
+ CONFLUENCE_PAT_KEYCHAIN_ACCOUNT=confluence-prod
214
+ CONFLUENCE_EXPORT_DEFAULT_DIR=/path/to/notes/wiki-exports
215
+ CONFLUENCE_EXPORT_STAGING_DIR=/absolute/path/to/conjira-cli/local/exports
216
+
217
+ JIRA_BASE_URL=https://jira.example.com
218
+ JIRA_PAT_KEYCHAIN_SERVICE=conjira-cli
219
+ JIRA_PAT_KEYCHAIN_ACCOUNT=jira-prod
220
+ ```
221
+
222
+ Store the Confluence PAT in Keychain:
223
+
224
+ ```bash
225
+ read -s "PAT?Enter Confluence PAT: "; echo
226
+ security add-generic-password -U -s conjira-cli -a confluence-prod -w "$PAT"
227
+ unset PAT
228
+ ```
229
+
230
+ Store the Jira PAT in Keychain:
231
+
232
+ ```bash
233
+ read -s "PAT?Enter Jira PAT: "; echo
234
+ security add-generic-password -U -s conjira-cli -a jira-prod -w "$PAT"
235
+ unset PAT
236
+ ```
237
+
238
+ On Linux or Windows, use environment variables or token files instead of Keychain. For example:
239
+
240
+ ```dotenv
241
+ CONFLUENCE_BASE_URL=https://confluence.example.com
242
+ CONFLUENCE_PAT=your-confluence-pat
243
+ CONFLUENCE_EXPORT_DEFAULT_DIR=/path/to/notes
244
+
245
+ JIRA_BASE_URL=https://jira.example.com
246
+ JIRA_PAT=your-jira-pat
247
+ ```
248
+
249
+ Or point the CLI at token files:
250
+
251
+ ```dotenv
252
+ CONFLUENCE_BASE_URL=https://confluence.example.com
253
+ CONFLUENCE_PAT_FILE=/path/to/confluence.token
254
+
255
+ JIRA_BASE_URL=https://jira.example.com
256
+ JIRA_PAT_FILE=/path/to/jira.token
257
+ ```
258
+
259
+ Then verify the connection:
260
+
261
+ ```bash
262
+ ./bin/conjira --env-file ./local/agent.env auth-check
263
+ ./bin/conjira --env-file ./local/agent.env jira-auth-check
264
+ ```
265
+
266
+ ## Common commands
267
+
268
+ Read a Confluence page:
269
+
270
+ ```bash
271
+ ./bin/conjira --env-file ./local/agent.env get-page --page-id 123456 --expand body.storage,space,version
272
+ ```
273
+
274
+ Export a Confluence page to Markdown:
275
+
276
+ ```bash
277
+ ./bin/conjira --env-file ./local/agent.env export-page-md --page-id 123456 --output-dir "/path/to/work-folder"
278
+ ```
279
+
280
+ Export a Confluence page tree to nested Markdown folders:
281
+
282
+ ```bash
283
+ ./bin/conjira --env-file ./local/agent.env export-tree-md --page-id 123456 --output-dir "/path/to/work-folder"
284
+ ```
285
+
286
+ Export grouped inline comment threads:
287
+
288
+ ```bash
289
+ ./bin/conjira --env-file ./local/agent.env export-inline-comments-md --page-id 123456 --status open --output-dir "/path/to/work-folder"
290
+ ```
291
+
292
+ Create or update a Confluence page:
293
+
294
+ ```bash
295
+ ./bin/conjira --env-file ./local/agent.env create-page --allow-write --space-key DOCS --parent-id 100001 --title "CLI test page" --body-html "<p>Hello from conjira</p>"
296
+ ./bin/conjira --env-file ./local/agent.env update-page --allow-write --page-id 100002 --append-html "<p>Updated by conjira</p>"
297
+ ```
298
+
299
+ Create or update a Confluence page from Markdown:
300
+
301
+ ```bash
302
+ ./bin/conjira --env-file ./local/agent.env create-page --allow-write --space-key DOCS --parent-id 100001 --title "Markdown page" --body-markdown "# Demo\n\n- Item A"
303
+ ./bin/conjira --env-file ./local/agent.env update-page --allow-write --page-id 100002 --append-markdown-file ./notes/update.md
304
+ ```
305
+
306
+ Replace one named section on an existing Confluence page:
307
+
308
+ ```bash
309
+ ./bin/conjira --env-file ./local/agent.env replace-section --allow-write --page-id 100002 --heading "Rollout plan" --section-markdown-file ./notes/rollout.md
310
+ ```
311
+
312
+ Move an existing Confluence page under a different parent page:
313
+
314
+ ```bash
315
+ ./bin/conjira --env-file ./local/agent.env move-page --dry-run --page-id 100002 --new-parent-id 100001
316
+ ./bin/conjira --env-file ./local/agent.env move-page --allow-write --page-id 100002 --new-parent-id 100001
317
+ ```
318
+
319
+ Preview a Confluence or Jira write first:
320
+
321
+ ```bash
322
+ ./bin/conjira --env-file ./local/agent.env update-page --dry-run --page-id 100002 --append-markdown-file ./notes/update.md
323
+ ./bin/conjira --env-file ./local/agent.env jira-create-issue --dry-run --project-key DEMO --issue-type-name Task --summary "Preview issue" --description "No write yet"
324
+ ```
325
+
326
+ Search Jira and fetch an issue:
327
+
328
+ ```bash
329
+ ./bin/conjira --env-file ./local/agent.env jira-search --jql 'project = DEMO ORDER BY created DESC' --limit 5
330
+ ./bin/conjira --env-file ./local/agent.env jira-get-issue --issue-key DEMO-123
331
+ ```
332
+
333
+ Create a Jira issue or add a comment:
334
+
335
+ ```bash
336
+ ./bin/conjira --env-file ./local/agent.env jira-create-issue --allow-write --project-key DEMO --issue-type-name Task --summary "CLI issue test" --description "Created from conjira"
337
+ ./bin/conjira --env-file ./local/agent.env jira-add-comment --allow-write --issue-key DEMO-123 --body "Comment from conjira"
338
+ ```
339
+
340
+ ## Configuration
341
+
342
+ The CLI resolves configuration in this order:
343
+
344
+ 1. explicit CLI flags such as `--base-url` and `--token`
345
+ 2. environment variables
346
+ 3. values loaded from `--env-file`
347
+
348
+ Confluence settings:
349
+
350
+ - `CONFLUENCE_BASE_URL`
351
+ - `CONFLUENCE_PAT`
352
+ - `CONFLUENCE_PAT_FILE`
353
+ - `CONFLUENCE_PAT_KEYCHAIN_SERVICE`
354
+ - `CONFLUENCE_PAT_KEYCHAIN_ACCOUNT`
355
+ - `CONFLUENCE_TIMEOUT_SECONDS`
356
+ - `CONFLUENCE_ALLOWED_SPACE_KEYS`
357
+ - `CONFLUENCE_ALLOWED_PARENT_IDS`
358
+ - `CONFLUENCE_ALLOWED_PAGE_IDS`
359
+ - `CONFLUENCE_EXPORT_DEFAULT_DIR`
360
+ - `CONFLUENCE_EXPORT_STAGING_DIR`
361
+
362
+ Jira settings:
363
+
364
+ - `JIRA_BASE_URL`
365
+ - `JIRA_PAT`
366
+ - `JIRA_PAT_FILE`
367
+ - `JIRA_PAT_KEYCHAIN_SERVICE`
368
+ - `JIRA_PAT_KEYCHAIN_ACCOUNT`
369
+ - `JIRA_TIMEOUT_SECONDS`
370
+ - `JIRA_ALLOWED_PROJECT_KEYS`
371
+ - `JIRA_ALLOWED_ISSUE_KEYS`
372
+
373
+ ## Safety model
374
+
375
+ This CLI intentionally does not implement delete commands for Confluence pages or Jira issues.
376
+
377
+ Write commands either require `--allow-write`, or `--dry-run` when you only want a preview. That means a copied read command does not mutate Confluence or Jira unless the caller explicitly opts in.
378
+
379
+ For stronger guardrails, define write allowlists in `local/agent.env`. If `CONFLUENCE_ALLOWED_*` or `JIRA_ALLOWED_*` values are set, writes fail closed outside the approved spaces, parents, pages, projects, or issue keys even if the PAT itself has broader permissions.
380
+
381
+ ## Common failure hints
382
+
383
+ When the CLI hits a common API failure, it now returns a `guidance` field alongside the raw error. The most common cases are:
384
+
385
+ - `401`: check the PAT, the credential source being used, and whether the base URL points at the right product host
386
+ - `403`: check product permissions and any configured allowlists
387
+ - `404`: check the page ID, issue key, or target path and confirm the PAT owner can see it in the web UI
388
+ - `409`: refresh live content and retry, especially for Confluence updates after concurrent edits
389
+ - `429` and `5xx`: retry after a short delay and reduce request volume if you are looping
390
+
391
+ ## Export strategy
392
+
393
+ Use `local/` only for machine-local config, temporary files, and staging artifacts. Final Markdown exports should usually go into your real notes folder, docs workspace, or knowledge base, not into the CLI repository itself.
394
+
395
+ The recommended pattern is to set `CONFLUENCE_EXPORT_DEFAULT_DIR` to an inbox or work folder, keep `CONFLUENCE_EXPORT_STAGING_DIR` pointed at `local/exports`, use `--output-dir` when the final destination is already known, and use `--staging-local` only when you want a short-lived preview.
396
+
397
+ ## Markdown import notes
398
+
399
+ Markdown upload is a best-effort conversion to Confluence storage HTML. It works well for common headings, paragraphs, lists, blockquotes, fenced code blocks, tables, links, images, and simple wiki-style links. It is not a perfect round-trip for complex Confluence macros, merged tables, or deeply nested layouts, so treat Markdown import as a practical authoring path rather than a lossless document converter.
400
+
401
+ Use `--body-file` and `--append-file` only for storage HTML files. If your source file is Markdown, use `--body-markdown-file` or `--append-markdown-file` so the CLI converts it before upload.
402
+
403
+ ## Agent usage
404
+
405
+ If another local coding agent needs to use this project, point it to [docs/AGENT_USAGE.md](docs/AGENT_USAGE.md). That document is written for tools that can run shell commands on the same machine.
406
+
407
+ ## License
408
+
409
+ This repository is released under the MIT License. See [LICENSE](LICENSE).