heinzel-atlassian
Read Jira issues and Confluence pages through Atlassian's CLI acli, the tracker and documents capabilities
(ADR 0028): a first-party
Heinzelmännchen plugin. It is independently released and installed explicitly:
hz system plugin add atlassian --confirm # a compatible plugin release; run it again to upgrade
hz system plugin remove heinzel-atlassian
Set up
The plugin does only what you could do yourself: every read runs acli, logged in as you (ADR 0035, proposed). It stores no token and needs no app an administrator registers. Install acli 1.3.39 or later (guide) and log in to both products, in the browser or with an API token without scopes:
acli jira auth login --web
acli confluence auth login --web
Name the site acli is logged in to, and bind the adapter, in your user configuration (never a project hz.toml,
which Heinzelmännchen ignores for both):
hz system config set atlassian.site_url https://acme.atlassian.net
hz system config set capabilities.tracker atlassian
hz system config set capabilities.documents atlassian
which together write
[atlassian]
site_url = "https://acme.atlassian.net"
[capabilities]
tracker = "atlassian"
documents = "atlassian"
Or per shell: HZ_ATLASSIAN__SITE_URL, HZ_CAPABILITIES__TRACKER=atlassian, HZ_CAPABILITIES__DOCUMENTS=atlassian.
site_url must be https://<site>.atlassian.net (a pasted .../wiki is trimmed). The plugin builds issue and page
links on it and accepts page URLs only on it. acli decides which site it reads. After a login with an API token,
an answer that names another site (an issue's self, a page's _links.base) is refused with acli jira auth switch
and the setting to change. After a browser login the check can't work: answers come through Atlassian's gateway
(api.atlassian.com/ex/<product>/<cloud id>), name no site, and are taken as they are, so keep acli on the site you
configured (acli jira auth switch, acli confluence auth switch), or links point at the wrong site. Matching the
cloud id would need a request of the plugin's own; doctor says so. Optionally,
atlassian.timeout sets the seconds each acli command may take (default 60), and atlassian.acli the program (a name
looked up on absolute PATH entries, or an absolute path; default acli). A project hz.toml can set none of the
three.
Upgrading from the release that stored an API token: the plugin no longer reads it. Remove it with your keychain's
own tool (on macOS: security delete-generic-password -s heinzel/atlassian -a atlassian-token), and drop
atlassian.email from your configuration.
Is it connected?
Bound automatically while it is the only installed adapter of a capability, ADR
0055. hz system connector list (or Settings → Connectors in hz ui) shows the site and the login command; whether acli is
logged in is only known after hz system connector test atlassian, which reads one Jira work item (acli jira workitem search --limit 1) and, when documents is bound to it, one Confluence space (acli confluence space list --limit 1),
15 s at most each, and only when you run it.
Use
Workflows ask for tracker and documents, never for Jira or Confluence:
from datetime import datetime
from heinzel import Document, Documents, Issue, Module, Tracker, Window
module = Module("digest", "Weekly digest.", requires=["tracker:read", "documents:read"])
@module.operation
def updated(tracker: Tracker, since: datetime, until: datetime) -> list[Issue]:
"""Issues updated this week."""
return tracker.issues_updated("WID", Window(since=since, until=until))
@module.operation
def plan(documents: Documents) -> Document:
"""The plan, as Markdown."""
return documents.read("https://acme.atlassian.net/wiki/spaces/WID/pages/123456/Widget+plan")
| Method | Capability | acli command |
|---|---|---|
issues_updated(project, window) |
tracker:read |
acli jira workitem search --jql 'project = "WID" AND updated >= <ms> AND updated < <ms> ORDER BY updated ASC, key ASC' --fields key,summary,status,updated,assignee,labels --paginate --json |
read(ref) |
documents:read |
acli confluence page view --id <id> --body-format storage --json |
- Projects are Jira project keys such as
WID(lower case is upper-cased); anything else is refused before acli runs, so no input reaches JQL unchecked. Windows are half-open[since, until)with timezone-aware times, sent as epoch milliseconds widened to whole minutes, which Jira compares as instants whatever your profile's time zone; the exact window is applied to the results, which come oldest first, each issue once. More than 1,000 issues in one window is refused with a request for a shorter one.stateis the status name,assigneethe display name,labelsthe issue's labels. - Documents are a page id (
123456) or a page URL on your site:/wiki/spaces/<space>/pages/<id>/...or/wiki/pages/viewpage.action?pageId=<id>. URLs on any other host are refused before acli runs; short links (/wiki/x/...) need the full URL. The page's storage format comes back as Markdown-flavoured text (headings, lists, tasks, links, tables, code blocks); images and macro settings are left out, image captions stay.revisionis the page version. - Not available through acli: a search for pages updated in a window (acli 1.3 has
page viewbut no page search or CQL), so thedocumentscapability staysread(ref)only, which is all it defines today.
hz atlassian info # this plugin, its version, the site, acli's path and the commands it runs
hz system capability list # who reads what, through which adapter and hosts
hz system doctor # acli and its version, the site and bindings; runs only `acli --version`, offline
Doctor doesn't check whether acli is logged in, because asking could reach Atlassian; the first read tells. Errors say
what to do: acli missing names its install and acli jira auth login; acli older than 1.3.39 names the upgrade; acli
logged out (unauthorized) names acli jira auth login or acli confluence auth login; a refusal names the
permission (Browse projects in Jira, View on the space in Confluence); a missing project or page says the account may
lack access; a rate limit says to retry later.
acli runs with an argument list (never a shell), no standard input, the home directory as working directory, an
allowlisted environment (PATH without relative entries, HOME, locale, proxy, XDG_* and D-Bus, and ACLI_*
variables; never HZ_CREDENTIAL_*), in its own process group under a deadline (SIGTERM, then SIGKILL for it and
anything it started; a descendant that left the group and keeps the output open counts as a timeout), with standard
output capped at 10 MiB and the last 64 KiB of standard error kept. Error messages are the plugin's own words: acli's
error text only picks the message and goes to the debug log (HZ_LOG_LEVEL=DEBUG), cleaned of escape sequences and
controls, redacted of anything shaped like a token and only then shortened.
The hosts hz system capability list shows are your site and api.atlassian.com, the gateway acli uses after a
browser login. acli is Atlassian's program with its own settings; what it sends besides the reads is Atlassian's
to document, not this plugin's.
The shapes of acli's --json output are assumed from Atlassian's REST APIs (issue objects, the Confluence v2 page),
not yet checked against a logged-in acli; the samples in tests/fixtures follow that assumption.
Development and release commands: repository guide.
Migration provenance: heinzel, before the 0.9 plugin-boundary migration.
Metadata
Release files for heinzel-atlassian 0.9.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| heinzel_atlassian-0.9.1.tar.gz | 92.5 kB | Without provenance | Details for heinzel_atlassian-0.9.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| heinzel_atlassian-0.9.1-py3-none-any.whl | Python 3 | none | any | Details for heinzel_atlassian-0.9.1-py3-none-any.whl |
Total release size: 123.2 kB
Release files / heinzel_atlassian-0.9.1.tar.gz
| Download URL | heinzel_atlassian-0.9.1.tar.gz |
|---|---|
| Size | 92.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3322fb62a2d0f2119861f23bfb728dfa4f3906669ae689ae61e486e49dba4122
|
|
BLAKE2b-256 checksum How to use checksums |
90ba0f9f1cb9acf8bdfbc3dd1bfac88f3f0343abfa2b9a4d1b6820907ab430c3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / heinzel_atlassian-0.9.1-py3-none-any.whl
| Download URL | heinzel_atlassian-0.9.1-py3-none-any.whl |
|---|---|
| Size | 30.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2b7f7c814b5c8239edf8b45e36e720771977b0354a41badfff9a552ad5585832
|
|
BLAKE2b-256 checksum How to use checksums |
a43bc175b1a9ae10afe5bd6c0eefd9ba60c6a32bd2862703d4a57c4e5490a9a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for heinzel-atlassian 0.9.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.