atlass 1.6.0 → 1.7.0

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 (3) hide show
  1. package/README.md +67 -308
  2. package/dist/cli.mjs +1180 -817
  3. package/package.json +9 -1
package/README.md CHANGED
@@ -1,373 +1,132 @@
1
1
  # atlass
2
2
 
3
- CLI to copy Jira issues and Confluence pages to Markdown, and push edits back to
4
- Confluence.
5
-
6
- Fetches an issue or page from Atlassian Cloud, converts its rich content to
7
- Markdown, writes a `.md` file with YAML frontmatter, and downloads any
8
- attachments alongside it. Confluence pages can be edited locally and updated
9
- back on the server.
3
+ CLI for Atlassian Cloud. Views Jira issues in the terminal, copies Jira issues
4
+ and Confluence pages to Markdown, pushes edits back, searches both, and shows
5
+ Bitbucket pipeline runs.
10
6
 
11
7
  ## Install
12
8
 
13
9
  ```bash
14
- pnpm install
15
- pnpm build
16
- pnpm link --global # exposes the `atlass` binary
10
+ npm install -g atlass
17
11
  ```
18
12
 
19
- Or run from source without linking:
20
-
21
- ```bash
22
- node dist/cli.mjs <command>
23
- ```
13
+ Or from source: `pnpm install && pnpm build && pnpm link --global`.
24
14
 
25
15
  ## Authentication
26
16
 
27
- Atlassian Cloud only. Auth uses your account email plus an API token
28
- (Basic auth). Create a token at
29
- `https://id.atlassian.com/manage-profile/security/api-tokens`.
17
+ Create an API token at
18
+ `https://id.atlassian.com/manage-profile/security/api-tokens`, then:
30
19
 
31
20
  ```bash
32
- atlass auth login
21
+ atlass auth login # prompts for site, email, and token
22
+ atlass auth status
23
+ atlass auth logout
33
24
  ```
34
25
 
35
- You are prompted for:
36
-
37
- - site, e.g. `acme.atlassian.net`
38
- - account email
39
- - API token
26
+ Site and email go in `~/.config/atlass/config.json`. The token goes in the OS
27
+ keyring. One account at a time.
40
28
 
41
- The login is verified against `/rest/api/3/myself` before anything is saved.
42
- The site and email are stored in `~/.config/atlass/config.json`
43
- (or `$XDG_CONFIG_HOME/atlass/config.json`). The API token is stored in the OS
44
- keyring (service `atlass`), never on disk.
29
+ Bitbucket needs its own Bitbucket-scoped token with pipeline and workspace read
30
+ scopes, since Atlassian tokens are scoped per product:
45
31
 
46
32
  ```bash
47
- atlass auth status # show current site/email and whether a token is stored
48
- atlass auth logout # remove config and delete the token from the keyring
33
+ atlass bitbucket login # prompts for workspace, default repo, and token
34
+ atlass bitbucket status
35
+ atlass bitbucket logout
49
36
  ```
50
37
 
51
- Only one account is supported at a time.
52
-
53
- ### Bitbucket
54
-
55
- Bitbucket Cloud is supported for viewing pipeline results. It uses the same
56
- Atlassian account email but a separate, Bitbucket-scoped API token (Atlassian
57
- tokens are scoped per product at creation, so a Jira token cannot be reused).
38
+ ## View
58
39
 
59
40
  ```bash
60
- atlass bitbucket login
41
+ atlass jira view PROJ-123
42
+ atlass jira view https://acme.atlassian.net/browse/PROJ-123
61
43
  ```
62
44
 
63
- You are prompted for:
64
-
65
- - workspace, e.g. `acme` (from `bitbucket.org/acme/<repo>`)
66
- - default repo slug (optional)
67
- - API token, created with the `read:pipeline` and workspace-read scopes at
68
- `https://id.atlassian.com/manage-profile/security/api-tokens` (select Bitbucket
69
- as the app)
45
+ Prints the issue to the terminal: fields, description, the last five comments
46
+ (`--all-comments` for all of them), and attachment names. The status is colored
47
+ by category and the Markdown is syntax highlighted, code blocks included; color
48
+ turns off automatically when piping, or with `NO_COLOR`, leaving plain Markdown.
70
49
 
71
- The login is verified against the workspace before anything is saved. The
72
- workspace and optional default repo are stored in the `bitbucket` block of
73
- `config.json`; the token is stored in the OS keyring under a separate entry.
74
-
75
- ```bash
76
- atlass bitbucket status # show workspace, default repo, and token presence
77
- atlass bitbucket logout # remove the Bitbucket config block and token
78
- ```
79
-
80
- `bitbucket login`/`logout` are independent of `auth login`/`logout`: logging out
81
- of one leaves the other intact.
82
-
83
- ## Usage
84
-
85
- ### Copy a Jira issue
50
+ ## Copy
86
51
 
87
52
  ```bash
88
53
  atlass jira copy PROJ-123
89
54
  atlass jira copy https://acme.atlassian.net/browse/PROJ-123
90
- atlass jira copy # prompts for the key or URL
91
- ```
92
-
93
- Accepts an issue key or any URL containing one. Writes `PROJ-123.md` to the
94
- current directory.
95
-
96
- ### Update a Jira issue
97
-
98
- Copy an issue, edit the Markdown, then push the description back:
99
-
100
- ```bash
101
- atlass jira update PROJ-123.md
102
- atlass jira update # prompts for the file path
103
- atlass jira update file.md --dry-run # show what would change, write nothing
104
- atlass jira update file.md --summary # also push the H1 as the issue summary
105
- ```
106
-
107
- The issue key comes from the file's frontmatter. The body is everything between
108
- the H1 and the `## Comments` section; the frontmatter, the H1, and the
109
- `## Comments` / `## Attachments` sections are not sent.
110
-
111
- Only the description is updated by default. Pass `--summary` to also push the H1
112
- as the new issue summary.
113
-
114
- Notes and safety:
115
-
116
- - The body is converted from Markdown to ADF. Only the standard constructs the
117
- copy produces round-trip (headings, lists, task lists, code, blockquotes,
118
- tables, rules, inline marks, links). Jira-specific content (panels, macros)
119
- was flattened to plain Markdown on copy and cannot be rebuilt. When the live
120
- description still contains such content, the update warns and asks for
121
- confirmation before overwriting.
122
- - Jira has no page-style version number, so staleness is checked against the
123
- frontmatter `updated` timestamp. If the issue changed since you copied it, the
124
- update aborts so you can re-copy. `--force` overrides this and the data-loss
125
- confirmation.
126
- - Image changes are not supported yet. External image URLs are kept as external
127
- media, but a local image reference aborts the update (edit text only), and a
128
- server-side image in the description is reported before it would be removed.
129
-
130
- ### Copy a Confluence page
131
-
132
- ```bash
133
55
  atlass confluence copy 123456
134
56
  atlass confluence copy https://acme.atlassian.net/wiki/spaces/DEV/pages/123456/Title
135
- atlass confluence copy # prompts for the id or URL
136
57
  ```
137
58
 
138
- Accepts a numeric page id or a page URL. Writes `123456-title-slug.md` to the
139
- current directory.
59
+ Writes `PROJ-123.md` or `123456-title-slug.md` to the current directory, with
60
+ attachments in a sibling `<name>.assets/` folder. Pass `--out` with a directory
61
+ or file path to write elsewhere. Existing files are overwritten.
140
62
 
141
- ### Update a Confluence page
63
+ Each file has YAML frontmatter, an H1, the body as Markdown, a `## Comments`
64
+ section, and an `## Attachments` section. Inline images link to the local copy
65
+ when they can be matched to an attachment.
142
66
 
143
- Copy a page, edit the Markdown, then push it back:
67
+ ## Update
68
+
69
+ Edit a copied file, then push it back:
144
70
 
145
71
  ```bash
72
+ atlass jira update PROJ-123.md
73
+ atlass jira update PROJ-123.md --summary # also push the H1 as the summary
146
74
  atlass confluence update 123456-title-slug.md
147
- atlass confluence update # prompts for the file path
148
- atlass confluence update file.md --dry-run # show what would change, write nothing
149
- atlass confluence update file.md --title # also rename the page to the H1
75
+ atlass confluence update file.md --title # also push the H1 as the title
150
76
  atlass confluence update file.md -m "fix typo"
151
77
  ```
152
78
 
153
- The page id and version come from the file's frontmatter, so the file is
154
- self-describing. The body is everything between the H1 and the `## Comments`
155
- section; the frontmatter, the H1, and the `## Comments` / `## Attachments`
156
- sections are not sent as page content.
157
-
158
- Only the body is updated by default. Pass `--title` to also push the H1 as the
159
- new page title.
160
-
161
- Notes and safety:
162
-
163
- - The body is converted from Markdown to ADF. Only the standard constructs the
164
- copy produces round-trip (headings, lists, task lists, code, blockquotes,
165
- tables, rules, inline marks, links, images). Confluence-specific content
166
- (panels, expands, macros, layouts) was flattened to plain Markdown on copy
167
- and cannot be rebuilt. When the live page still contains such content, the
168
- update warns and asks for confirmation before overwriting.
169
- - Before writing, the current server version is checked against the frontmatter
170
- version. If the page changed since you copied it, the update aborts so you can
171
- re-copy. `--force` overrides this and the data-loss confirmation.
172
- - Images referenced in the body are uploaded as attachments (matched by name and
173
- size, so unchanged images are not re-uploaded). Local paths resolve relative
174
- to the Markdown file; a missing local image aborts the update. External image
175
- URLs are kept as external media.
176
- - Each update adds a version with the message `Updated via atlass` (override
177
- with `--message`).
178
-
179
- ### Search Jira issues
180
-
181
- ```bash
182
- atlass jira search "safari login" # free text
183
- atlass jira search --project PROJ --assignee me # my open issues in PROJ
184
- atlass jira search --status "In Progress"
185
- atlass jira search --jql "project = PROJ AND labels = regression"
186
- atlass jira search # recent issues
187
- ```
188
-
189
- Friendly filters (`--project`, `--assignee`, `--status`, text) are AND'd
190
- together and ordered by most recently updated. `--assignee me` maps to the
191
- current user. `--jql` takes a raw query and cannot be combined with the friendly
192
- filters. Prints one issue per line (`KEY status summary`); use `--json` for
193
- machine output. Only the first `--limit` results are shown (default 25, max
194
- 100).
195
-
196
- ### List Jira projects
197
-
198
- ```bash
199
- atlass jira projects # every project you can browse
200
- atlass jira projects pay # filter by key or name
201
- atlass jira projects --json # machine output
202
- ```
203
-
204
- A discovery aid for the `--project` filter above: it fetches every project
205
- (paginated, ordered by key) and prints one per line as an aligned `KEY Name`
206
- list. An optional query filters by key or name server-side. `--json` emits
207
- `{ key, name, id, type, url }` per project.
208
-
209
- ### List Jira statuses
210
-
211
- ```bash
212
- atlass jira statuses # every status on the site
213
- atlass jira statuses progress # filter by name
214
- atlass jira statuses --project PROJ # statuses used by one project
215
- atlass jira statuses --json # machine output
216
- ```
79
+ Both accept `--dry-run` to preview and `--force` to skip the checks below. The
80
+ body sent is everything between the H1 and `## Comments`.
217
81
 
218
- A discovery aid for the `--status` filter above. Without `--project` it lists
219
- every status on the site; with `--project` it lists the statuses that project's
220
- issue types use (flattened to one list). An optional query filters by name
221
- (case-insensitive substring). Statuses are collapsed by name and category, then
222
- ordered by workflow lifecycle (To Do, then In Progress, then Done) and name.
223
- Prints an aligned `Name Category` list; `--json` emits
224
- `{ name, id, category, categoryKey }` per status.
82
+ - The update aborts if the issue or page changed on the server since the copy.
83
+ - Panels, macros, expands, and layouts were flattened on copy and cannot be
84
+ rebuilt. If the live content still has them, the update asks before
85
+ overwriting.
86
+ - Confluence uploads local images referenced in the body as attachments. Jira
87
+ update does not support image changes yet.
225
88
 
226
- ### Search Confluence pages
89
+ ## Search
227
90
 
228
91
  ```bash
229
- atlass confluence search "onboarding"
230
- atlass confluence search --space DOCS
92
+ atlass jira search "safari login"
93
+ atlass jira search --project PROJ --assignee me --status "In Progress"
94
+ atlass jira search --jql "project = PROJ AND labels = regression"
95
+ atlass confluence search "onboarding" --space DOCS
231
96
  atlass confluence search --cql "label = runbook ORDER BY created DESC"
232
- atlass confluence search # recent pages
233
97
  ```
234
98
 
235
- Friendly mode always constrains to pages, so every result is copy-able. `--cql`
236
- takes a raw query and cannot be combined with `--space` or text. Prints one page
237
- per line (`id space title`); `--json` and `--limit` work as for Jira.
99
+ Filters combine with AND and sort by most recently updated. `--jql` and `--cql`
100
+ replace the friendly filters. `--limit` defaults to 25, max 100. `--json` prints
101
+ machine output. Add `--copy` to pick results interactively and copy each one,
102
+ with `--out` as the target directory.
238
103
 
239
- ### Copy from search results
240
-
241
- Add `--copy` to any search to pick results interactively and copy each to
242
- Markdown (multi-select, needs an interactive terminal). With `--copy`, `--out`
243
- is a directory that every selected file is written into:
104
+ Discovery aids for the filters:
244
105
 
245
106
  ```bash
246
- atlass jira search --project PROJ --copy --out ./tickets/
247
- atlass confluence search --space DOCS --copy
107
+ atlass jira projects [query]
108
+ atlass jira statuses [query] [--project PROJ]
248
109
  ```
249
110
 
250
- Copying continues on failure and reports a summary at the end.
251
-
252
- ### View Bitbucket pipelines
253
-
254
- ```bash
255
- atlass bitbucket pipelines # recent runs for the default repo
256
- atlass bitbucket pipelines --repo acme/web # a specific workspace/repo
257
- atlass bitbucket pipelines --repo web # bare slug, under the config workspace
258
- atlass bitbucket pipelines --limit 50 --json
259
- ```
260
-
261
- Lists recent pipeline runs, newest first, one per line
262
- (`#build status ref duration age creator`). Status shows the result
263
- (`SUCCESSFUL`/`FAILED`/...) once a run completes, else its state
264
- (`IN_PROGRESS`/`PENDING`/...). The repo comes from `--repo` (a `workspace/slug`
265
- or a bare slug under the configured workspace), falling back to the configured
266
- default repo. `--limit` defaults to 25, max 100. `--json` emits the full mapped
267
- objects.
268
-
269
- ```bash
270
- atlass bitbucket pipeline 124 # one run and its steps
271
- atlass bitbucket pipeline 124 --repo acme/web
272
- ```
273
-
274
- Shows a run summary (status, ref, commit, trigger, duration, creator) and its
275
- step list (name, status, duration). The build number you pass is resolved to the
276
- run directly, falling back to a bounded scan of recent runs if needed.
277
-
278
- ### Output location
279
-
280
- By default files are written to the current directory, named after the issue
281
- key (Jira) or `<id>-<title-slug>` (Confluence). Use `--out` to override:
111
+ ## Bitbucket pipelines
282
112
 
283
113
  ```bash
284
- atlass jira copy PROJ-123 --out ./tickets/ # directory: ./tickets/PROJ-123.md
285
- atlass jira copy PROJ-123 --out ./bug.md # explicit file path
114
+ atlass bitbucket pipelines # recent runs for the default repo
115
+ atlass bitbucket pipelines --repo acme/web
116
+ atlass bitbucket pipeline 124 # one run and its steps
286
117
  ```
287
118
 
288
- Existing files are overwritten.
289
-
290
- ## Output format
291
-
292
- Each file is:
293
-
294
- - YAML frontmatter with metadata
295
- - an H1 heading (issue summary / page title)
296
- - the body, converted from ADF to Markdown
297
- - a `## Comments` section (Jira comments / Confluence footer comments)
298
- - an `## Attachments` section linking every downloaded file
299
-
300
- Jira frontmatter: `key`, `type`, `status`, `assignee`, `reporter`, `priority`,
301
- `labels`, `created`, `updated`, `url`.
302
-
303
- Confluence frontmatter: `title`, `id`, `space`, `version`, `author`, `created`,
304
- `updated`, `url`.
305
-
306
- Example (Jira):
307
-
308
- ```markdown
309
- ---
310
- key: "PROJ-123"
311
- type: "Bug"
312
- status: "In Progress"
313
- assignee: "Dana Scully"
314
- reporter: "Fox Mulder"
315
- priority: "High"
316
- labels:
317
- - "regression"
318
- url: "https://acme.atlassian.net/browse/PROJ-123"
319
- ---
320
-
321
- # Login button does nothing on Safari
322
-
323
- Steps to reproduce...
324
-
325
- ## Comments
326
-
327
- ### Fox Mulder - 2025-07-01 10:30
328
-
329
- Reproduced on 17.5.
330
-
331
- ## Attachments
332
-
333
- - [screenshot.png](PROJ-123.assets/screenshot.png)
334
- ```
335
-
336
- ### Attachments
337
-
338
- All attachments are downloaded into a sibling `<name>.assets/` folder and
339
- listed under `## Attachments`. Inline images are linked to the local copy where
340
- they can be matched:
341
-
342
- - Confluence media nodes carry the attachment file id, so inline images resolve
343
- reliably.
344
- - Jira media nodes usually expose only a filename, so inline images resolve when
345
- that filename matches an attachment; otherwise they render as
346
- `[embedded media: ...]` and the file is still captured in the attachments
347
- folder and section.
119
+ `--repo` takes `workspace/slug` or a bare slug under the configured workspace.
120
+ `--limit` and `--json` work as for search.
348
121
 
349
122
  ## Development
350
123
 
351
124
  ```bash
352
- pnpm test # run unit tests
353
- pnpm check # format, lint, typecheck (add --fix to auto-fix)
125
+ pnpm test # unit tests
126
+ pnpm check # format, lint, typecheck (--fix to auto-fix)
354
127
  pnpm build # build dist/cli.mjs
355
128
  pnpm dev # build in watch mode
356
129
  ```
357
130
 
358
- ### Layout
359
-
360
- - `src/cli.ts` command wiring (commander)
361
- - `src/commands/` `auth`, `jira`, `confluence`, `bitbucket` command handlers
362
- - `src/api/` fetch client, Jira, Confluence and Bitbucket endpoints, attachment up/download
363
- - `src/adf/` ADF to Markdown and Markdown to ADF converters (unit tested)
364
- - `src/markdown/` frontmatter, comments, attachments, media resolver, update source
365
- - `src/config.ts`, `src/credentials.ts` config file and keyring
366
- - `src/util/` key/id parsing and output path resolution
367
-
368
- The ADF to Markdown converter in `src/adf/to-markdown.ts` is a single hand
369
- rolled walker shared by both commands. Confluence page bodies are requested as
370
- `atlas_doc_format` so they flow through the same converter as Jira. The reverse
371
- direction, `src/adf/from-markdown.ts`, tokenizes Markdown with `marked` and
372
- emits ADF for the Confluence update command; it covers the same clean subset the
373
- copy produces.
131
+ Commands live in `src/commands/`, API clients in `src/api/`, and the ADF
132
+ converters in `src/adf/`.