@fatecannotbealtered-/jira-cli 1.0.1 → 1.0.3

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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.0.3] - 2026-05-26
11
+
12
+ ### Fixed
13
+
14
+ - **Semantic exit codes** — validation, auth, and config failures now return non-zero exit codes (via `SilentErr`); `doctor` and `login` work correctly in CI scripts.
15
+ - **Audit logging on failed writes** — write commands are logged even when the operation fails.
16
+ - **`FilterSprintFields`** — camelCase sprint fields (`startDate`, `endDate`) filter correctly with `--fields`.
17
+ - **Config file corruption detection** — invalid JSON in `~/.jira-cli/config.json` returns a clear parse error.
18
+ - **`issue edit --description`** — plain text is converted to ADF, matching `issue create`.
19
+ - **Agile API pagination** — sprint/board list, backlog, epics, and epic issues fetch all pages instead of truncating at ~50 items.
20
+ - **`ListWorklogs` pagination** — worklogs beyond the first page are included.
21
+ - **`search --order-by`** — skips appending `ORDER BY` when JQL already contains one.
22
+ - **`issue delete --dry-run`** — no longer prompts for confirmation before previewing.
23
+ - **`issue bulk-transition`** — `skipped` and `failed` counts are reported separately in JSON output.
24
+ - **E2E script** — sprint move (K7) runs before issue cleanup; `JIRA_E2E_CLEANUP=0` is honored.
25
+
26
+ ### Added
27
+
28
+ - **`cmd.Run()` / `Main()`** — testable CLI entry point with correct exit code propagation.
29
+ - **Comprehensive unit tests** — 100% statement coverage across all packages; httptest-based command integration tests.
30
+ - **`internal/api/agile_page.go`** — shared pagination helper for Jira Agile API endpoints.
31
+
32
+ ### Changed
33
+
34
+ - **Minimum Go version** — `go.mod` updated to Go 1.24 (uses `testing.T.Chdir` in tests).
35
+
36
+ ### Documentation
37
+
38
+ - Clarify `search --fields` (Jira fetch) vs `issue get/list --fields` (output trimming).
39
+ - Document `issue delete --dry-run` skips confirmation; remove misleading `sprint close --force` wording.
40
+ - Add `epic list` / `epic issues` to README; document `filter run --raw/--fields`.
41
+ - Document stdout (success JSON) vs stderr (error JSON); `doctor` exit code and `authValid` checks.
42
+ - Note npm install requires `curl`; add `install-skill` and `issue list` vs `search` JSON/jq examples.
43
+
44
+ ## [1.0.2] - 2026-05-14
45
+
46
+ ### Fixed
47
+
48
+ - **Retry loop now respects context cancellation** — long-running API calls with rate limiting or server errors can now be interrupted by the caller.
49
+ - **Upload retry loop now respects context cancellation** — file uploads honor context cancellation during retries.
50
+ - **Token sanitization improved** — audit logging now handles `--token=value` format for all case variations (e.g., `--TOKEN=`, `--Token=`).
51
+ - **Config file corruption detection** — invalid JSON in `~/.jira-cli/config.json` now returns an error instead of silently continuing with empty values.
52
+ - **Timing attack prevention** — confirmation prompts use constant-time comparison to prevent timing-based information leakage.
53
+
54
+ ### Security
55
+
56
+ - **Audit logging uses constant-time comparison** to prevent timing attacks on confirmation inputs.
57
+ - **Sensitive flags aligned with JDC-only PAT authentication** — audit sanitization targets only `--token` and `-t` since this CLI uses PAT only, no password support.
58
+
10
59
  ## [1.0.1] - 2026-05-06
11
60
 
12
61
  ### Fixed
@@ -22,7 +71,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
22
71
  - **`filter run` supports `--raw` and `--fields`** flags, consistent with `search` and `issue list`.
23
72
  - **`board backlog` and `board epics` support `--limit`** flag (default 50, max 200).
24
73
  - **`issue watch`/`unwatch`/`vote`/`unvote` produce JSON output** with `--json` flag.
25
- - **`parseTimeSpent` supports `d` (days) and `w` (weeks)** units — `1d` = 8h, `1w` = 5d (Jira defaults).
74
+ - **`parseTimeSpent` supports `d` (days) and `w` (weeks)`** units — `1d` = 8h, `1w` = 5d (Jira defaults).
26
75
  - **`make test` now runs `gofmt` and `go vet`** before unit tests.
27
76
  - **Release workflow extracts version-specific notes** from CHANGELOG.md for GitHub Release body.
28
77
 
@@ -58,6 +107,8 @@ Initial release of jira-cli for Jira Data Center.
58
107
  - SKILL.md with JSON output schemas, error codes, exit codes, and complete flag reference.
59
108
  - GitHub PR template for contributors.
60
109
 
61
- [Unreleased]: https://github.com/fatecannotbealtered/jira-cli/compare/v1.0.1...HEAD
110
+ [Unreleased]: https://github.com/fatecannotbealtered/jira-cli/compare/v1.0.3...HEAD
111
+ [1.0.3]: https://github.com/fatecannotbealtered/jira-cli/compare/v1.0.2...v1.0.3
112
+ [1.0.2]: https://github.com/fatecannotbealtered/jira-cli/compare/v1.0.1...v1.0.2
62
113
  [1.0.1]: https://github.com/fatecannotbealtered/jira-cli/compare/v1.0.0...v1.0.1
63
114
  [1.0.0]: https://github.com/fatecannotbealtered/jira-cli/releases/tag/v1.0.0
package/README.md CHANGED
@@ -39,18 +39,19 @@ This project is shared for **personal learning, research, and everyday productiv
39
39
  Recommended flow: install the CLI from npm, then install the AI Agent Skill with `npx skills add`.
40
40
 
41
41
  ```bash
42
- # Install CLI
42
+ # Install CLI (requires curl on PATH — used to download the binary)
43
43
  npm install -g @fatecannotbealtered-/jira-cli
44
44
 
45
- # Install CLI Skill
46
- npx skills add fatecannotbealtered/jira-cli -y -g
45
+ # Install CLI Skill (pick one)
46
+ npx skills add fatecannotbealtered/jira-cli -y -g # via skills registry
47
+ jira-cli install-skill # bundled skill → ~/.openclaw/skills
47
48
 
48
49
  # Login and verify
49
50
  jira-cli login
50
- jira-cli doctor
51
+ jira-cli doctor --json # check authValid is true (see JSON Output)
51
52
  ```
52
53
 
53
- The CLI package provides the `jira-cli` binary; the Skill package teaches compatible AI coding assistants how to use it safely. If you are an AI Agent helping a user set this up, run the same steps and ask the user to complete any interactive browser or terminal prompts.
54
+ The CLI package provides the `jira-cli` binary; the Skill teaches compatible AI coding assistants how to use it safely. `install-skill` copies the bundled skill from the npm package (or release tarball) into `~/.openclaw/skills` for OpenClaw-compatible agents. If you are an AI Agent helping a user set this up, run the same steps and ask the user to complete any interactive browser or terminal prompts.
54
55
 
55
56
  ### Alternative: Go install
56
57
 
@@ -91,7 +92,7 @@ Environment variables take precedence over the config file. This is the recommen
91
92
  ```bash
92
93
  export JIRA_HOST=https://jira.company.com
93
94
  export JIRA_TOKEN=<your-personal-access-token>
94
- jira-cli doctor --json
95
+ jira-cli doctor --json # verify authValid is true
95
96
  ```
96
97
 
97
98
  ### Generating a PAT
@@ -115,7 +116,8 @@ jira-cli issue create --project PROJ --summary "Fix login bug" --type Bug
115
116
  jira-cli issue create --project PROJ --summary "Sized story" --field "Story Points=5"
116
117
  jira-cli issue edit PROJ-123 --priority High --assignee me
117
118
  jira-cli issue edit PROJ-123 --field "Story Points=8" --field "Team=Backend"
118
- jira-cli issue delete PROJ-123 --force # --force skips confirmation
119
+ jira-cli issue delete PROJ-123 --force # --force skips confirmation prompt
120
+ jira-cli issue delete PROJ-123 --dry-run --json # preview delete (no confirmation prompt)
119
121
 
120
122
  # Clone
121
123
  jira-cli issue clone PROJ-123
@@ -165,7 +167,16 @@ jira-cli sprint list --board 42
165
167
  jira-cli sprint active --board 42
166
168
  jira-cli sprint create --board 42 --name "Sprint 5" --start-date 2024-02-01 --end-date 2024-02-14
167
169
  jira-cli sprint move --sprint 10 --issues PROJ-123,PROJ-124
168
- jira-cli sprint close --sprint 10 --force
170
+ jira-cli sprint close --sprint 10
171
+ jira-cli sprint close --sprint 10 --dry-run # preview without closing
172
+ ```
173
+
174
+ ### Epic Management
175
+
176
+ ```bash
177
+ jira-cli epic list --board 42
178
+ jira-cli epic list --board 42 --done # completed epics only
179
+ jira-cli epic issues PROJ-1 --board 42
169
180
  ```
170
181
 
171
182
  ### Board & Backlog
@@ -186,31 +197,52 @@ jira-cli user search --query "john"
186
197
  jira-cli user me
187
198
  jira-cli filter list
188
199
  jira-cli filter run <filterId>
200
+ jira-cli filter run <filterId> --json --fields key,summary,status
201
+ jira-cli filter run <filterId> --json --raw
189
202
  ```
190
203
 
191
204
  ## JSON Output
192
205
 
193
- All commands support `--json` for machine-readable output. By default, issue and sprint data is returned in a **flat, token-efficient format** (ideal for AI Agents):
206
+ All commands support `--json` for machine-readable output. **Success JSON goes to stdout; error JSON goes to stderr** — pipe or capture stdout for data, check `$?` and stderr for failures.
207
+
208
+ By default, issue and sprint data is returned in a **flat, token-efficient format** (ideal for AI Agents):
194
209
 
195
210
  ```bash
196
211
  # Flat JSON (default) — minimal fields, low token cost
197
212
  jira-cli issue get PROJ-123 --json
198
213
  jira-cli search "project = PROJ" --json | jq '.issues[].key'
199
214
 
200
- # Select only the fields you need
215
+ # issue list returns a bare array; search wraps issues in pagination metadata
216
+ # filter run with --fields also returns a bare trimmed array
217
+ jira-cli issue list --project PROJ --json | jq '.[].key'
218
+ jira-cli search "project = PROJ" --json | jq '.issues[].key'
219
+ jira-cli filter run 12345 --json --fields key,summary | jq '.[].key'
220
+
221
+ # Trim flat JSON output (issue get / issue list / sprint / filter run)
201
222
  jira-cli issue get PROJ-123 --json --fields key,summary,status,assignee
202
223
 
224
+ # search --fields controls which fields Jira fetches (API request), not output trimming
225
+ jira-cli search "project = PROJ" --fields summary,status,customfield_10001 --json
226
+
203
227
  # Raw Jira API response (full nested structure)
204
228
  jira-cli issue get PROJ-123 --json --raw
205
229
 
206
- # Clean output for scripts (suppress all non-JSON noise)
230
+ # Clean output for scripts (suppress all non-JSON noise on stdout)
207
231
  jira-cli issue get PROJ-123 --json --quiet
208
232
 
209
233
  # Preview destructive operations without executing
210
234
  jira-cli issue delete PROJ-123 --dry-run --json
211
235
  ```
212
236
 
213
- Error responses include machine-readable error codes and actionable hints:
237
+ ### Verify connectivity (`doctor`)
238
+
239
+ When using `--json`, check the `authValid` field (exit code 3 on auth/config failure):
240
+
241
+ ```bash
242
+ jira-cli doctor --json | jq '.authValid' # must be true
243
+ ```
244
+
245
+ Error responses (stderr) include machine-readable error codes and actionable hints:
214
246
 
215
247
  ```json
216
248
  {
@@ -260,13 +292,15 @@ Credentials stored at `~/.jira-cli/config.json` (permissions: 0600):
260
292
 
261
293
  | Flag | Commands | Description |
262
294
  |---|---|---|
263
- | `--raw` | `issue get`, `issue list`, `search`, `sprint list`, `sprint issues`, `sprint active` | Return raw Jira API response instead of flat format |
264
- | `--fields` | `issue get`, `issue list`, `sprint list`, `sprint issues` | Output only specified fields (e.g. `--fields key,summary,status`) |
295
+ | `--raw` | `issue get`, `issue list`, `search`, `filter run`, `sprint list`, `sprint issues`, `sprint active` | Return raw Jira API response instead of flat format |
296
+ | `--fields` | `issue get`, `issue list`, `sprint list`, `sprint issues`, `filter run` | **Output trimming** — include only listed fields in flat JSON (e.g. `--fields key,summary,status`) |
297
+ | `--fields` | `search` only | **Jira fetch fields** — comma-separated fields to request from the API (e.g. `--fields summary,status,customfield_10001`); does not trim flat output |
265
298
 
266
299
  ## Troubleshooting
267
300
 
268
301
  | Issue | Solution |
269
302
  |---|---|
303
+ | npm install fails / curl not found | Ensure `curl` is on PATH (required by npm postinstall to download the binary) |
270
304
  | Config not found | Run `jira-cli login` or set `JIRA_HOST` and `JIRA_TOKEN` env vars |
271
305
  | Authentication failed | Regenerate PAT in your Jira DC profile settings |
272
306
  | Permission denied | Check your PAT scope and project permissions |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fatecannotbealtered-/jira-cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Full-featured Jira Data Center CLI for humans and AI Agents — manage issues, sprints, boards, epics, projects, users, and filters from your terminal",
5
5
  "keywords": [
6
6
  "jira",
@@ -8,9 +8,11 @@ metadata: {"openclaw":{"emoji":"🎯","requires":{"bins":["jira-cli"]}}}
8
8
 
9
9
  Jira Data Center CLI for humans and AI Agents. Supports **Jira DC only** (self-hosted), not Jira Cloud.
10
10
 
11
- > Install CLI: `npm install -g @fatecannotbealtered-/jira-cli`
11
+ > Install CLI: `npm install -g @fatecannotbealtered-/jira-cli` (requires `curl` on PATH)
12
12
  >
13
- > Install Skill: `npx skills add fatecannotbealtered/jira-cli -y -g`
13
+ > Install Skill (pick one):
14
+ > - `npx skills add fatecannotbealtered/jira-cli -y -g`
15
+ > - `jira-cli install-skill` (bundled skill → `~/.openclaw/skills`)
14
16
 
15
17
  ## Prerequisites
16
18
 
@@ -20,15 +22,18 @@ Before using any command, authenticate with a Jira DC instance. Follow these ste
20
22
  2. Ask the user for a **Personal Access Token (PAT)**. If they don't have one, guide them:
21
23
  "Log in to your Jira DC → click your profile avatar → Personal Access Tokens → Create token."
22
24
  3. Run `jira-cli login --host <URL> --token <PAT>` to save credentials.
23
- 4. Run `jira-cli doctor --json` to verify connectivity. If `authValid` is `true`, you're ready.
25
+ 4. Run `jira-cli doctor --json` to verify connectivity. Check that `authValid` is `true` (exit code 3 on auth/config failure).
24
26
 
25
27
  **Important:** Credentials are saved locally at `~/.jira-cli/config.json`. Environment variables `JIRA_HOST` and `JIRA_TOKEN` override the config file — use them for CI or when the user prefers not to save credentials.
26
28
 
27
29
  **Always use `--json` flag when parsing output.** Without it, output is human-formatted and not suitable for programmatic use.
28
30
 
31
+ **Stdout vs stderr:** Success JSON is written to **stdout**; error JSON is written to **stderr**. Capture stdout for data; check exit code and stderr for failures.
32
+
29
33
  ## Safety
30
34
 
31
35
  - **Do NOT use `--force` on destructive commands unless the user explicitly asks.** Commands like `issue delete` prompt for confirmation by default. Skipping confirmation with `--force` is irreversible.
36
+ - **`issue delete --dry-run` skips confirmation** — dry-run is evaluated before the confirmation prompt.
32
37
  - **Use `--dry-run` before write operations** to preview what will happen without executing. Example: `issue create --project PROJ --summary "test" --type Task --dry-run --json`.
33
38
  - **AI Agents can make mistakes.** Always confirm with the user before executing `issue delete`, `issue bulk-transition`, `sprint close`, or any operation that modifies multiple issues.
34
39
  - All write operations are recorded in `~/.jira-cli/audit/` for traceability.
@@ -38,11 +43,10 @@ Before using any command, authenticate with a Jira DC instance. Follow these ste
38
43
  ```bash
39
44
  # View issues (flat JSON by default — token-efficient)
40
45
  jira-cli issue get PROJ-123 --json
41
- jira-cli issue get PROJ-123 --json --fields key,summary,status,assignee # Only specific fields
46
+ jira-cli issue get PROJ-123 --json --fields key,summary,status,assignee # Output trimming (flat JSON)
42
47
  jira-cli issue get PROJ-123 --json --raw # Full Jira API response
43
- jira-cli issue list --project PROJ --json
44
- jira-cli issue list --project PROJ --status "In Progress" --assignee me --json
45
- jira-cli issue list --project PROJ --type Bug --priority High --limit 20 --json
48
+ jira-cli issue list --project PROJ --json # Returns bare array of flat issues
49
+ jira-cli issue list --project PROJ --json --fields key,summary,status # Trimmed array
46
50
 
47
51
  # Create and edit
48
52
  jira-cli issue create --project PROJ --summary "Fix login bug" --type Bug --json
@@ -51,6 +55,7 @@ jira-cli issue create --project PROJ --summary "Sized story" --type Story --fiel
51
55
  jira-cli issue edit PROJ-123 --summary "Updated summary" --priority Medium
52
56
  jira-cli issue edit PROJ-123 --field "Story Points=8" --field "Team=Backend"
53
57
  jira-cli issue delete PROJ-123 --force # Skip confirmation prompt
58
+ jira-cli issue delete PROJ-123 --dry-run --json # Preview delete (no confirmation prompt)
54
59
 
55
60
  # Clone an issue
56
61
  jira-cli issue clone PROJ-123 --json # Clone with default summary
@@ -110,7 +115,7 @@ jira-cli search "project = PROJ" --limit 100 --json
110
115
  jira-cli search "project = PROJ" --all --json # Fetch ALL results (auto-paginate)
111
116
  jira-cli search "project = PROJ" --count # Only show total count
112
117
  jira-cli search "project = PROJ" --order-by updated --json
113
- jira-cli search "type = Bug AND priority = High" --fields key,summary,status --json
118
+ jira-cli search "type = Bug AND priority = High" --fields summary,status,customfield_10001 --json # Jira fetch fields (API request)
114
119
  ```
115
120
 
116
121
  ## Sprint Management
@@ -124,7 +129,8 @@ jira-cli sprint issues --sprint 10 --json
124
129
  jira-cli sprint create --board 42 --name "Sprint 5" --start-date 2024-02-01 --end-date 2024-02-14 --json
125
130
  jira-cli sprint update --sprint 10 --goal "Complete payment refactor"
126
131
  jira-cli sprint move --sprint 10 --issues PROJ-123,PROJ-124,PROJ-125
127
- jira-cli sprint close --sprint 10 --force # --force skips confirmation
132
+ jira-cli sprint close --sprint 10 --json
133
+ jira-cli sprint close --sprint 10 --dry-run --json # Preview without closing (no confirmation prompt)
128
134
  ```
129
135
 
130
136
  ## Board & Backlog
@@ -175,6 +181,8 @@ jira-cli filter list --json
175
181
  jira-cli filter get <filterId> --json
176
182
  jira-cli filter create --name "My Bugs" --jql "assignee = me AND type = Bug" --json
177
183
  jira-cli filter run <filterId> --json
184
+ jira-cli filter run <filterId> --json --fields key,summary,status # Output trimming
185
+ jira-cli filter run <filterId> --json --raw # Raw Jira search response
178
186
  jira-cli filter delete <filterId>
179
187
  ```
180
188
 
@@ -218,9 +226,9 @@ jira-cli sprint move --sprint 11 --issues PROJ-200,PROJ-201,PROJ-202
218
226
 
219
227
  ## Guardrails
220
228
 
221
- - Always run `jira-cli doctor --json` to verify auth before bulk operations
222
- - `issue delete` requires typing the issue key to confirm. Use `--force` to skip confirmation in automated workflows
223
- - `sprint close` is irreversible. Use `--force` to skip confirmation
229
+ - Always run `jira-cli doctor --json` and verify **`authValid` is `true`** before bulk operations (exit code 3 on failure)
230
+ - `issue delete` requires typing the issue key to confirm. Use `--force` to skip confirmation in automated workflows; `--dry-run` skips confirmation
231
+ - `sprint close` has no confirmation prompt — use `--dry-run` to preview; confirm with the user before closing
224
232
  - Use `--json` flag when parsing output in scripts or AI workflows
225
233
  - Use `--dry-run` to preview what a write command would do without executing it
226
234
  - Use `--quiet` with `--json` to suppress all non-JSON output (clean pipe-friendly output)
@@ -237,13 +245,36 @@ jira-cli sprint move --sprint 11 --issues PROJ-200,PROJ-201,PROJ-202
237
245
 
238
246
  ## Output Control Flags
239
247
 
240
- These flags are available on read commands (`issue get`, `issue list`, `search`, `sprint list`, `sprint issues`):
248
+ Two different meanings for `--fields`:
249
+
250
+ | Command | `--fields` meaning |
251
+ |---------|-------------------|
252
+ | `search` | **Jira fetch fields** — comma-separated fields to request from the API (e.g. `summary,status,customfield_10001`) |
253
+ | `issue get`, `issue list`, `sprint list`, `sprint issues`, `filter run` | **Output trimming** — include only listed keys in flat JSON (e.g. `key,summary,status`) |
254
+
255
+ Other read-command flags:
241
256
 
242
- - `--raw` — Return the full raw Jira API response instead of the token-efficient flat format
243
- - `--fields key,summary,status` — Output only the specified fields (flat JSON mode only)
257
+ - `--raw` — Return the full raw Jira API response instead of the token-efficient flat format (on `issue get/list`, `search`, `filter run`, `sprint list/issues/active`)
244
258
 
245
259
  ## JSON Output Schemas
246
260
 
261
+ ### List vs search JSON shape
262
+
263
+ | Command | Flat `--json` shape |
264
+ |---------|---------------------|
265
+ | `issue list` | Bare array: `[{key, summary, ...}, ...]` |
266
+ | `search`, `filter run` (default) | Object with pagination: `{total, startAt, maxResults, issues: [...]}` |
267
+ | `filter run --fields ...` | Bare trimmed array (like `issue list --fields`) |
268
+ | `issue get` | Single flat issue object |
269
+
270
+ **jq examples:**
271
+
272
+ ```bash
273
+ jira-cli issue list --project PROJ --json | jq '.[].key'
274
+ jira-cli search "project = PROJ" --json | jq '.issues[].key'
275
+ jira-cli filter run 12345 --json | jq '.issues[].status'
276
+ ```
277
+
247
278
  ### Flat Issue (default with --json)
248
279
 
249
280
  ```json
@@ -276,7 +307,7 @@ These flags are available on read commands (`issue get`, `issue list`, `search`,
276
307
  }
277
308
  ```
278
309
 
279
- ### Error Response (with --json)
310
+ ### Error Response (with --json, written to stderr)
280
311
 
281
312
  ```json
282
313
  {