@fatecannotbealtered-/jira-cli 1.0.6 → 1.1.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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.1.0] - 2026-06-06
11
+
12
+ ### Added
13
+
14
+ - **Agent JSON envelope** — default JSON success and failure responses now share a stable envelope: `ok`, `schema_version`, `data`/`error`, and `meta.duration_ms`.
15
+ - **Confirm-token write flow** — JSON write commands now support the non-interactive `--dry-run` → `--confirm <token>` flow. Dry-run responses include a change preview, `confirm_token`, and `expires_at`; execution validates that the token still matches the operation.
16
+ - **Self-description commands** — added `context`, and expanded `reference` and `doctor` output for agent discovery and environment checks.
17
+ - **Structured error taxonomy** — error envelopes now include stable `E_*` codes and `retryable` hints for automated retry decisions.
18
+
19
+ ### Changed
20
+
21
+ - **JSON is the agent contract** — stdout now contains exactly one JSON document for normal command responses; human-readable output requires `--format text`.
22
+ - **Error JSON moved to stdout** — machine-readable failures now use the same stdout channel and envelope shape as successes. Progress, prompts, warnings, and text-mode errors remain on stderr.
23
+ - **Exit code semantics** — exit codes now follow the agent contract: `2` bad args, `3` not found, `4` auth/permission, `5` confirmation required, `6` conflict, `7` retryable transient failure, `8` timeout.
24
+ - **Interactive login is text-only** — default JSON mode requires `jira-cli login --host <url> --token <pat>`; interactive login requires `--format text`.
25
+ - **`doctor` output** — JSON output now reports a `checks` list with `check`, `status`, `message`, and `fix` fields instead of the old `authValid` shape.
26
+
27
+ ### Fixed
28
+
29
+ - **JSON write safety** — confirmed JSON writes no longer fall through to stdin prompts after token validation.
30
+ - **Stable confirmation hashing** — write-command confirm tokens include the full operation details and stable slice handling in tests.
31
+
10
32
  ## [1.0.6] - 2026-06-05
11
33
 
12
34
  ### Added
@@ -137,7 +159,8 @@ Initial release of jira-cli for Jira Data Center.
137
159
  - SKILL.md with JSON output schemas, error codes, exit codes, and complete flag reference.
138
160
  - GitHub PR template for contributors.
139
161
 
140
- [Unreleased]: https://github.com/fatecannotbealtered/jira-cli/compare/v1.0.6...HEAD
162
+ [Unreleased]: https://github.com/fatecannotbealtered/jira-cli/compare/v1.1.0...HEAD
163
+ [1.1.0]: https://github.com/fatecannotbealtered/jira-cli/compare/v1.0.6...v1.1.0
141
164
  [1.0.6]: https://github.com/fatecannotbealtered/jira-cli/compare/v1.0.5...v1.0.6
142
165
  [1.0.5]: https://github.com/fatecannotbealtered/jira-cli/compare/v1.0.4...v1.0.5
143
166
  [1.0.4]: https://github.com/fatecannotbealtered/jira-cli/compare/v1.0.3...v1.0.4
package/README.md CHANGED
@@ -48,8 +48,8 @@ npm install -g @fatecannotbealtered-/jira-cli
48
48
  # Install CLI Skill (required) — copies into your agent-supported skills directory
49
49
  npx skills add fatecannotbealtered/jira-cli -y -g
50
50
 
51
- # Login and verify
52
- jira-cli login
51
+ # Login and verify (interactive login is text mode)
52
+ jira-cli --format text login
53
53
  jira-cli doctor
54
54
  ```
55
55
 
@@ -70,7 +70,7 @@ Download from [GitHub Releases](https://github.com/fatecannotbealtered/jira-cli/
70
70
  ```bash
71
71
  jira-cli update --check # check latest GitHub Release
72
72
  jira-cli update # update a standalone binary
73
- jira-cli update --version v1.2.3 # install a specific release
73
+ jira-cli update --version v1.1.0 # install a specific release
74
74
  ```
75
75
 
76
76
  `jira-cli update` verifies `checksums.txt` before replacing the current binary. If the CLI was installed through npm, the command will recommend the package-manager path instead:
@@ -88,7 +88,7 @@ jira-cli supports **Jira Data Center** (private deployments) with **Personal Acc
88
88
  ### Interactive login
89
89
 
90
90
  ```bash
91
- jira-cli login
91
+ jira-cli --format text login
92
92
  # Jira host: https://jira.company.com
93
93
  # Personal Access Token (PAT): ****
94
94
  # ✔ Logged in as John Doe (johndoe)
@@ -110,7 +110,7 @@ Environment variables take precedence over the config file. This is the recommen
110
110
  ```bash
111
111
  export JIRA_HOST=https://jira.company.com
112
112
  export JIRA_TOKEN=<your-personal-access-token>
113
- jira-cli doctor # verify authValid is true
113
+ jira-cli doctor # verify .data.config.auth_status is "valid"
114
114
  ```
115
115
 
116
116
  ### Generating a PAT
@@ -129,47 +129,47 @@ jira-cli issue get PROJ-123
129
129
  jira-cli issue list --project PROJ
130
130
  jira-cli issue list --project PROJ --status "In Progress" --assignee me
131
131
 
132
- # Create & Edit
133
- jira-cli issue create --project PROJ --summary "Fix login bug" --type Bug
134
- jira-cli issue create --project PROJ --summary "Sized story" --field "Story Points=5"
135
- jira-cli issue edit PROJ-123 --priority High --assignee me
136
- jira-cli issue edit PROJ-123 --field "Story Points=8" --field "Team=Backend"
137
- jira-cli issue delete PROJ-123 --force # --force skips confirmation prompt
138
- jira-cli issue delete PROJ-123 --dry-run # preview delete (no confirmation prompt)
132
+ # Create & Edit (direct human execution uses text mode; JSON automation uses dry-run/confirm)
133
+ jira-cli --format text issue create --project PROJ --summary "Fix login bug" --type Bug
134
+ jira-cli --format text issue create --project PROJ --summary "Sized story" --field "Story Points=5"
135
+ jira-cli --format text issue edit PROJ-123 --priority High --assignee me
136
+ jira-cli --format text issue edit PROJ-123 --field "Story Points=8" --field "Team=Backend"
137
+ jira-cli --format text issue delete PROJ-123 --force # skips text-mode confirmation prompt
138
+ jira-cli issue delete PROJ-123 --dry-run # preview delete and get confirm_token
139
139
 
140
140
  # Clone
141
- jira-cli issue clone PROJ-123
142
- jira-cli issue clone PROJ-123 --summary "New title" --with-links
141
+ jira-cli --format text issue clone PROJ-123
142
+ jira-cli --format text issue clone PROJ-123 --summary "New title" --with-links
143
143
 
144
144
  # Status
145
145
  jira-cli issue transitions PROJ-123 # List available transitions
146
- jira-cli issue transition PROJ-123 "Done" # Status name required as argument
146
+ jira-cli --format text issue transition PROJ-123 "Done" # Status name required as argument
147
147
 
148
148
  # Bulk Transition
149
- jira-cli issue bulk-transition "Done" --issues PROJ-1,PROJ-2,PROJ-3
150
- jira-cli issue bulk-transition "In Progress" --jql "sprint = 10 AND status = 'To Do'"
149
+ jira-cli --format text issue bulk-transition "Done" --issues PROJ-1,PROJ-2,PROJ-3
150
+ jira-cli --format text issue bulk-transition "In Progress" --jql "sprint = 10 AND status = 'To Do'"
151
151
 
152
152
  # Collaboration
153
- jira-cli issue assign PROJ-123 me # Assign to current user
154
- jira-cli issue assign PROJ-123 johndoe # Assign by username (DC uses name, not accountId)
155
- jira-cli issue watch PROJ-123
156
- jira-cli issue vote PROJ-123
153
+ jira-cli --format text issue assign PROJ-123 me # Assign to current user
154
+ jira-cli --format text issue assign PROJ-123 johndoe # Assign by username (DC uses name, not accountId)
155
+ jira-cli --format text issue watch PROJ-123
156
+ jira-cli --format text issue vote PROJ-123
157
157
 
158
158
  # Comments
159
- jira-cli issue comment add PROJ-123 --body "Fixed in PR #42"
159
+ jira-cli --format text issue comment add PROJ-123 --body "Fixed in PR #42"
160
160
  jira-cli issue comment list PROJ-123
161
161
 
162
162
  # Worklogs
163
- jira-cli issue worklog add PROJ-123 --time 2h --comment "Debugging"
163
+ jira-cli --format text issue worklog add PROJ-123 --time 2h --comment "Debugging"
164
164
  jira-cli issue worklog list PROJ-123
165
165
 
166
166
  # Links & Attachments
167
- jira-cli issue link PROJ-123 --to PROJ-456 --type "blocks"
168
- jira-cli issue attach PROJ-123 --file ./screenshot.png
167
+ jira-cli --format text issue link PROJ-123 --to PROJ-456 --type "blocks"
168
+ jira-cli --format text issue attach PROJ-123 --file ./screenshot.png
169
169
  jira-cli issue attachments PROJ-123 # List attachments
170
170
  jira-cli issue attachments PROJ-123 --out ./downloads # Download all attachments
171
171
  jira-cli issue attachments PROJ-123 --out ./downloads --id 4609477 # Download one by ID
172
- jira-cli issue remote-link PROJ-123 --url https://pr.url --title "PR #42"
172
+ jira-cli --format text issue remote-link PROJ-123 --url https://pr.url --title "PR #42"
173
173
  ```
174
174
 
175
175
  ### Search (JQL)
@@ -186,9 +186,9 @@ jira-cli search "project = PROJ" --limit 100 --order-by updated
186
186
  ```bash
187
187
  jira-cli sprint list --board 42
188
188
  jira-cli sprint active --board 42
189
- jira-cli sprint create --board 42 --name "Sprint 5" --start-date 2024-02-01 --end-date 2024-02-14
190
- jira-cli sprint move --sprint 10 --issues PROJ-123,PROJ-124
191
- jira-cli sprint close --sprint 10
189
+ jira-cli --format text sprint create --board 42 --name "Sprint 5" --start-date 2024-02-01 --end-date 2024-02-14
190
+ jira-cli --format text sprint move --sprint 10 --issues PROJ-123,PROJ-124
191
+ jira-cli --format text sprint close --sprint 10
192
192
  jira-cli sprint close --sprint 10 --dry-run # preview without closing
193
193
  ```
194
194
 
@@ -226,7 +226,7 @@ jira-cli --format raw filter run <filterId>
226
226
 
227
227
  `jira-cli` defaults to machine-readable JSON, so scripts and AI Agents can omit output flags. Use `--format json|text|raw` to choose the result format:
228
228
 
229
- - `json` is the default. Success JSON goes to stdout; error JSON goes to stderr.
229
+ - `json` is the default. Success and error envelopes both go to stdout; logs, prompts, and warnings go to stderr.
230
230
  - `text` is for human-readable summaries, tables, colors, diff/log text, and prompts.
231
231
  - `raw` is for unwrapped raw command results where supported. Unsupported commands return an argument error instead of silently downgrading.
232
232
 
@@ -234,18 +234,18 @@ jira-cli --format raw filter run <filterId>
234
234
 
235
235
  `--compact` only affects JSON. `--fields` only works with JSON output. `--quiet` suppresses auxiliary text output only; it does not suppress JSON or raw main results.
236
236
 
237
- By default, issue and sprint data is returned in a **flat, token-efficient JSON format** (ideal for AI Agents):
237
+ By default, issue and sprint data is returned in the envelope's `data` field as a **flat, token-efficient JSON format** (ideal for AI Agents):
238
238
 
239
239
  ```bash
240
240
  # Flat JSON (default) — minimal fields, low token cost
241
241
  jira-cli issue get PROJ-123
242
- jira-cli search "project = PROJ" | jq '.issues[].key'
242
+ jira-cli search "project = PROJ" | jq '.data.issues[].key'
243
243
 
244
- # issue list returns a bare array; search wraps issues in pagination metadata
245
- # filter run with --fields also returns a bare trimmed array
246
- jira-cli issue list --project PROJ | jq '.[].key'
247
- jira-cli search "project = PROJ" | jq '.issues[].key'
248
- jira-cli filter run 12345 --fields key,summary | jq '.[].key'
244
+ # issue list returns an array in .data; search wraps issues in pagination metadata under .data
245
+ # filter run with --fields also returns a trimmed array in .data
246
+ jira-cli issue list --project PROJ | jq '.data[].key'
247
+ jira-cli search "project = PROJ" | jq '.data.issues[].key'
248
+ jira-cli filter run 12345 --fields key,summary | jq '.data[].key'
249
249
 
250
250
  # Trim flat JSON output (issue get / issue list / sprint / filter run)
251
251
  jira-cli issue get PROJ-123 --fields key,summary,status,assignee
@@ -266,22 +266,36 @@ jira-cli --compact issue get PROJ-123
266
266
  jira-cli issue delete PROJ-123 --dry-run
267
267
  ```
268
268
 
269
+ JSON-mode write commands use a two-step confirmation flow:
270
+
271
+ ```bash
272
+ TOKEN=$(jira-cli issue create --project PROJ --summary "Fix login bug" --dry-run --compact | jq -r '.data.confirm_token')
273
+ jira-cli issue create --project PROJ --summary "Fix login bug" --confirm "$TOKEN"
274
+ ```
275
+
269
276
  ### Verify connectivity (`doctor`)
270
277
 
271
- With the default JSON output, check the `authValid` field (exit code 3 on auth/config failure):
278
+ With the default JSON output, check `data.config.auth_status` (exit code 4 on auth/config failure):
272
279
 
273
280
  ```bash
274
- jira-cli doctor | jq '.authValid' # must be true
281
+ jira-cli doctor | jq -e '.data.config.auth_status == "valid"'
275
282
  ```
276
283
 
277
- Error responses (stderr) include machine-readable error codes and actionable hints:
284
+ Error responses use the same stdout envelope and include machine-readable error codes and retry hints:
278
285
 
279
286
  ```json
280
287
  {
281
- "error": "Jira API error 404: Issue does not exist",
282
- "statusCode": 404,
283
- "errorCode": "NOT_FOUND",
284
- "hint": "Verify the issue key exists and you have permission to view it"
288
+ "ok": false,
289
+ "schema_version": "1.0",
290
+ "error": {
291
+ "code": "E_NOT_FOUND",
292
+ "message": "Jira API error 404: Issue does not exist",
293
+ "details": {
294
+ "status_code": 404,
295
+ "hint": "Verify the resource key/ID exists and you have permission to view it"
296
+ },
297
+ "retryable": false
298
+ }
285
299
  }
286
300
  ```
287
301
 
@@ -321,6 +335,7 @@ Credentials stored at `~/.jira-cli/config.json` (permissions: 0600):
321
335
  | `--force` | Skip interactive confirmation prompts |
322
336
  | `--quiet` | Suppress auxiliary text output; does not suppress JSON/raw main results |
323
337
  | `--dry-run` | Show what would be done without executing (supported by write/update commands) |
338
+ | `--confirm <token>` | Execute a JSON-mode write command using the token returned by `--dry-run` |
324
339
 
325
340
  ### Per-command flags
326
341
 
@@ -337,7 +352,7 @@ Credentials stored at `~/.jira-cli/config.json` (permissions: 0600):
337
352
  | Issue | Solution |
338
353
  |---|---|
339
354
  | npm install fails / curl not found | Ensure `curl` is on PATH (required by npm postinstall to download the binary) |
340
- | Config not found | Run `jira-cli login` or set `JIRA_HOST` and `JIRA_TOKEN` env vars |
355
+ | Config not found | Run `jira-cli --format text login`, `jira-cli login --host <url> --token <pat>`, or set `JIRA_HOST` and `JIRA_TOKEN` env vars |
341
356
  | Authentication failed | Regenerate PAT in your Jira DC profile settings |
342
357
  | Permission denied | Check your PAT scope and project permissions |
343
358
  | Resource not found | Verify the issue key or project key exists |
@@ -348,7 +363,7 @@ Credentials stored at `~/.jira-cli/config.json` (permissions: 0600):
348
363
 
349
364
  - Credentials are stored locally at `~/.jira-cli/config.json` with `0600` file permissions (user-only readable)
350
365
  - Config directory is created with `0700` permissions
351
- - PAT input is hidden during `jira-cli login` (uses terminal secure input)
366
+ - PAT input is hidden during `jira-cli --format text login` (uses terminal secure input)
352
367
  - All communication uses HTTPS (host must start with `https://`)
353
368
  - No credentials are logged or transmitted to third parties
354
369
  - Environment variables `JIRA_HOST` and `JIRA_TOKEN` take precedence over config file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fatecannotbealtered-/jira-cli",
3
- "version": "1.0.6",
3
+ "version": "1.1.0",
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",
@@ -17,8 +17,8 @@ npm install -g @fatecannotbealtered-/jira-cli
17
17
  # Install CLI Skill (required) — copies into your agent-supported skills directory
18
18
  npx skills add fatecannotbealtered/jira-cli -y -g
19
19
 
20
- # Login and verify
21
- jira-cli login
20
+ # Login and verify (interactive login is text mode)
21
+ jira-cli --format text login
22
22
  jira-cli doctor
23
23
  ```
24
24
 
@@ -47,22 +47,30 @@ Before using any command, authenticate with a Jira DC instance. Follow these ste
47
47
  2. Ask the user for a **Personal Access Token (PAT)**. If they don't have one, guide them:
48
48
  "Log in to your Jira DC → click your profile avatar → Personal Access Tokens → Create token."
49
49
  3. Run `jira-cli login --host <URL> --token <PAT>` to save credentials.
50
- 4. Run `jira-cli doctor` to verify connectivity. Check that `authValid` is `true` (exit code 3 on auth/config failure).
50
+ 4. Run `jira-cli doctor` to verify connectivity. Check that `.data.config.auth_status` is `"valid"` (exit code 4 on auth/config failure).
51
51
 
52
52
  **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.
53
53
 
54
54
  **Do not add output flags for programmatic parsing.** JSON is the default. Use `--format text` only when the user wants human-readable tables or summaries.
55
55
 
56
- **Stdout vs stderr:** Success JSON is written to **stdout** by default; error JSON is written to **stderr**. Capture stdout for data; check exit code and stderr for failures.
56
+ **Stdout vs stderr:** Success and error JSON envelopes are written to **stdout** by default. Progress, prompts, warnings, and text-mode errors are written to **stderr**. Capture stdout for data and error envelopes; use exit codes for control flow.
57
57
 
58
58
  ## Safety
59
59
 
60
- - **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.
61
- - **`issue delete --dry-run` skips confirmation** dry-run is evaluated before the confirmation prompt.
60
+ - **Do NOT use `--force` on destructive commands unless the user explicitly asks.** In text mode, commands like `issue delete` prompt for confirmation by default. Skipping confirmation with `--force` is irreversible.
61
+ - **Use `--dry-run` before JSON write operations**, inspect `.data.preview`, then execute the same command with `--confirm <token>` from `.data.confirm_token`.
62
+ - **`issue delete --dry-run` skips confirmation** — dry-run is evaluated before any text-mode confirmation prompt.
62
63
  - **Use `--dry-run` before write operations** to preview what will happen without executing. Example: `issue create --project PROJ --summary "test" --type Task --dry-run`.
63
64
  - **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.
64
65
  - All write operations are recorded in `~/.jira-cli/audit/` for traceability.
65
66
 
67
+ JSON write flow:
68
+
69
+ ```bash
70
+ TOKEN=$(jira-cli issue create --project PROJ --summary "Fix login bug" --dry-run --compact | jq -r '.data.confirm_token')
71
+ jira-cli issue create --project PROJ --summary "Fix login bug" --confirm "$TOKEN"
72
+ ```
73
+
66
74
  ## Issue Management
67
75
 
68
76
  ```bash
@@ -70,61 +78,62 @@ Before using any command, authenticate with a Jira DC instance. Follow these ste
70
78
  jira-cli issue get PROJ-123
71
79
  jira-cli issue get PROJ-123 --fields key,summary,status,assignee # Output trimming (flat JSON)
72
80
  jira-cli --format raw issue get PROJ-123 # Full Jira API response
73
- jira-cli issue list --project PROJ # Returns bare array of flat issues
81
+ jira-cli issue list --project PROJ # Returns envelope with flat issue array in .data
74
82
  jira-cli issue list --project PROJ --fields key,summary,status # Trimmed array
75
83
 
76
84
  # Create and edit
77
- jira-cli issue create --project PROJ --summary "Fix login bug" --type Bug
78
- jira-cli issue create --project PROJ --summary "New feature" --type Story --assignee me --priority High
79
- jira-cli issue create --project PROJ --summary "Sized story" --type Story --field "Story Points=5"
80
- jira-cli issue edit PROJ-123 --summary "Updated summary" --priority Medium
81
- jira-cli issue edit PROJ-123 --field "Story Points=8" --field "Team=Backend"
82
- jira-cli issue delete PROJ-123 --force # Skip confirmation prompt
83
- jira-cli issue delete PROJ-123 --dry-run # Preview delete (no confirmation prompt)
85
+ # For direct human execution, use --format text. For JSON automation, use dry-run/confirm.
86
+ jira-cli --format text issue create --project PROJ --summary "Fix login bug" --type Bug
87
+ jira-cli --format text issue create --project PROJ --summary "New feature" --type Story --assignee me --priority High
88
+ jira-cli --format text issue create --project PROJ --summary "Sized story" --type Story --field "Story Points=5"
89
+ jira-cli --format text issue edit PROJ-123 --summary "Updated summary" --priority Medium
90
+ jira-cli --format text issue edit PROJ-123 --field "Story Points=8" --field "Team=Backend"
91
+ jira-cli --format text issue delete PROJ-123 --force # Skip text-mode confirmation prompt
92
+ jira-cli issue delete PROJ-123 --dry-run # Preview delete and get confirm_token
84
93
 
85
94
  # Clone an issue
86
- jira-cli issue clone PROJ-123 # Clone with default summary
87
- jira-cli issue clone PROJ-123 --summary "New title" # Clone with custom summary
88
- jira-cli issue clone PROJ-123 --with-links # Clone with issue links
95
+ jira-cli --format text issue clone PROJ-123 # Clone with default summary
96
+ jira-cli --format text issue clone PROJ-123 --summary "New title" # Clone with custom summary
97
+ jira-cli --format text issue clone PROJ-123 --with-links # Clone with issue links
89
98
 
90
99
  # Status transitions
91
100
  jira-cli issue transitions PROJ-123 # List available transitions
92
- jira-cli issue transition PROJ-123 "In Progress" # Transition to status (name required)
93
- jira-cli issue transition PROJ-123 "Done"
101
+ jira-cli --format text issue transition PROJ-123 "In Progress" # Transition to status (name required)
102
+ jira-cli --format text issue transition PROJ-123 "Done"
94
103
 
95
104
  # Bulk transition
96
- jira-cli issue bulk-transition "Done" --issues PROJ-1,PROJ-2,PROJ-3
97
- jira-cli issue bulk-transition "In Progress" --jql "project = PROJ AND sprint = 10 AND status = 'To Do'"
105
+ jira-cli --format text issue bulk-transition "Done" --issues PROJ-1,PROJ-2,PROJ-3
106
+ jira-cli --format text issue bulk-transition "In Progress" --jql "project = PROJ AND sprint = 10 AND status = 'To Do'"
98
107
 
99
108
  # Assignment and watching
100
- jira-cli issue assign PROJ-123 me # Assign to current user
101
- jira-cli issue assign PROJ-123 johndoe # Assign by username (DC uses name, not accountId)
102
- jira-cli issue unassign PROJ-123
103
- jira-cli issue watch PROJ-123
104
- jira-cli issue unwatch PROJ-123
109
+ jira-cli --format text issue assign PROJ-123 me # Assign to current user
110
+ jira-cli --format text issue assign PROJ-123 johndoe # Assign by username (DC uses name, not accountId)
111
+ jira-cli --format text issue unassign PROJ-123
112
+ jira-cli --format text issue watch PROJ-123
113
+ jira-cli --format text issue unwatch PROJ-123
105
114
  jira-cli issue watchers PROJ-123
106
- jira-cli issue vote PROJ-123
107
- jira-cli issue unvote PROJ-123
115
+ jira-cli --format text issue vote PROJ-123
116
+ jira-cli --format text issue unvote PROJ-123
108
117
 
109
118
  # Comments
110
- jira-cli issue comment add PROJ-123 --body "Fixed in PR #42"
119
+ jira-cli --format text issue comment add PROJ-123 --body "Fixed in PR #42"
111
120
  jira-cli issue comment list PROJ-123
112
- jira-cli issue comment delete PROJ-123 --id <commentId>
121
+ jira-cli --format text issue comment delete PROJ-123 --id <commentId>
113
122
 
114
123
  # Worklogs
115
- jira-cli issue worklog add PROJ-123 --time 2h --comment "Debugging session"
116
- jira-cli issue worklog add PROJ-123 --time 1h30m --started "2024-01-15T10:00:00.000+0000"
124
+ jira-cli --format text issue worklog add PROJ-123 --time 2h --comment "Debugging session"
125
+ jira-cli --format text issue worklog add PROJ-123 --time 1h30m --started "2024-01-15T10:00:00.000+0000"
117
126
  jira-cli issue worklog list PROJ-123
118
127
 
119
128
  # Links
120
129
  jira-cli issue link-types # List available link types
121
- jira-cli issue link PROJ-123 --to PROJ-456 --type "blocks"
122
- jira-cli issue unlink <linkId>
123
- jira-cli issue remote-link PROJ-123 --url https://pr.url --title "PR #42"
130
+ jira-cli --format text issue link PROJ-123 --to PROJ-456 --type "blocks"
131
+ jira-cli --format text issue unlink <linkId>
132
+ jira-cli --format text issue remote-link PROJ-123 --url https://pr.url --title "PR #42"
124
133
  jira-cli issue remote-links PROJ-123
125
134
 
126
135
  # Attachments
127
- jira-cli issue attach PROJ-123 --file ./screenshot.png
136
+ jira-cli --format text issue attach PROJ-123 --file ./screenshot.png
128
137
  jira-cli issue attachments PROJ-123 # list metadata (incl. content URL)
129
138
  jira-cli issue attachments PROJ-123 --out ./dl # download all -> [{id,filename,path,mimeType}]
130
139
  jira-cli issue attachments PROJ-123 --out ./dl --id 4609477 # download a single attachment by ID
@@ -153,10 +162,10 @@ jira-cli sprint list --board 42
153
162
  jira-cli sprint list --board 42 --state active
154
163
  jira-cli sprint active --board 42 # Active sprint + issues
155
164
  jira-cli sprint issues --sprint 10
156
- jira-cli sprint create --board 42 --name "Sprint 5" --start-date 2024-02-01 --end-date 2024-02-14
157
- jira-cli sprint update --sprint 10 --goal "Complete payment refactor"
158
- jira-cli sprint move --sprint 10 --issues PROJ-123,PROJ-124,PROJ-125
159
- jira-cli sprint close --sprint 10
165
+ jira-cli --format text sprint create --board 42 --name "Sprint 5" --start-date 2024-02-01 --end-date 2024-02-14
166
+ jira-cli --format text sprint update --sprint 10 --goal "Complete payment refactor"
167
+ jira-cli --format text sprint move --sprint 10 --issues PROJ-123,PROJ-124,PROJ-125
168
+ jira-cli --format text sprint close --sprint 10
160
169
  jira-cli sprint close --sprint 10 --dry-run # Preview without closing (no confirmation prompt)
161
170
  ```
162
171
 
@@ -206,11 +215,11 @@ jira-cli user search --query "john" --assignable --project PROJ
206
215
  ```bash
207
216
  jira-cli filter list
208
217
  jira-cli filter get <filterId>
209
- jira-cli filter create --name "My Bugs" --jql "assignee = me AND type = Bug"
218
+ jira-cli --format text filter create --name "My Bugs" --jql "assignee = me AND type = Bug"
210
219
  jira-cli filter run <filterId>
211
220
  jira-cli filter run <filterId> --fields key,summary,status # Output trimming
212
221
  jira-cli --format raw filter run <filterId> # Raw Jira search response
213
- jira-cli filter delete <filterId>
222
+ jira-cli --format text filter delete <filterId>
214
223
  ```
215
224
 
216
225
  ## Workflow Examples
@@ -227,10 +236,10 @@ jira-cli issue get PROJ-123
227
236
  jira-cli issue transitions PROJ-123
228
237
 
229
238
  # 4. Transition to Done
230
- jira-cli issue transition PROJ-123 "Done"
239
+ jira-cli --format text issue transition PROJ-123 "Done"
231
240
 
232
241
  # 5. Add a comment
233
- jira-cli issue comment add PROJ-123 --body "Completed and deployed to staging"
242
+ jira-cli --format text issue comment add PROJ-123 --body "Completed and deployed to staging"
234
243
  ```
235
244
 
236
245
  ### Sprint planning workflow
@@ -245,16 +254,17 @@ jira-cli sprint active --board 42
245
254
  jira-cli board backlog --board 42
246
255
 
247
256
  # 4. Create next sprint
248
- jira-cli sprint create --board 42 --name "Sprint 6" --start-date 2024-02-15 --end-date 2024-02-28
257
+ jira-cli --format text sprint create --board 42 --name "Sprint 6" --start-date 2024-02-15 --end-date 2024-02-28
249
258
 
250
259
  # 5. Move issues to sprint
251
- jira-cli sprint move --sprint 11 --issues PROJ-200,PROJ-201,PROJ-202
260
+ jira-cli --format text sprint move --sprint 11 --issues PROJ-200,PROJ-201,PROJ-202
252
261
  ```
253
262
 
254
263
  ## Guardrails
255
264
 
256
- - Always run `jira-cli doctor` and verify **`authValid` is `true`** before bulk operations (exit code 3 on failure)
257
- - `issue delete` requires typing the issue key to confirm. Use `--force` to skip confirmation in automated workflows; `--dry-run` skips confirmation
265
+ - Always run `jira-cli doctor` and verify **`.data.config.auth_status == "valid"`** before bulk operations (exit code 4 on auth/config failure)
266
+ - In JSON mode, write commands require `--dry-run` followed by `--confirm <token>` unless the command explicitly documents otherwise
267
+ - In text mode, `issue delete` requires typing the issue key to confirm. Use `--force` only when the user explicitly asked to skip that prompt; `--dry-run` skips confirmation
258
268
  - `sprint close` has no confirmation prompt — use `--dry-run` to preview; confirm with the user before closing
259
269
  - Omit output flags when parsing output in scripts or AI workflows; JSON is the default
260
270
  - Use `--dry-run` to preview what a write command would do without executing it
@@ -268,9 +278,10 @@ jira-cli sprint move --sprint 11 --issues PROJ-200,PROJ-201,PROJ-202
268
278
  - `--format json|text|raw` — Control output format. Default: `json`
269
279
  - `--compact` — Emit compact JSON (only with `--format json`)
270
280
  - `--json` — Compatibility alias for `--format json`; do not recommend it for new workflows
271
- - `--force` — Skip interactive confirmation prompts (for CI/Agent automation)
281
+ - `--force` — Skip interactive confirmation prompts in text mode
272
282
  - `--quiet` — Suppress auxiliary text output; does not suppress JSON/raw main results
273
283
  - `--dry-run` — Show what would be done without executing (supported by write/update commands)
284
+ - `--confirm <token>` — Execute a JSON-mode write command using the token returned by `--dry-run`
274
285
 
275
286
  ## Output Control Flags
276
287
 
@@ -292,20 +303,30 @@ Other read-command flags:
292
303
 
293
304
  | Command | Default JSON shape |
294
305
  |---------|---------------------|
295
- | `issue list` | Bare array: `[{key, summary, ...}, ...]` |
306
+ All default JSON responses are wrapped:
307
+
308
+ ```json
309
+ {"ok":true,"schema_version":"1.0","data":{},"meta":{"duration_ms":0}}
310
+ ```
311
+
312
+ The command-specific payload is in `.data`:
313
+
314
+ | Command | `.data` shape |
315
+ |---------|---------------|
316
+ | `issue list` | Array: `[{key, summary, ...}, ...]` |
296
317
  | `search`, `filter run` (default) | Object with pagination: `{total, startAt, maxResults, issues: [...]}` |
297
- | `filter run --fields ...` | Bare trimmed array (like `issue list --fields`) |
318
+ | `filter run --fields ...` | Trimmed array (like `issue list --fields`) |
298
319
  | `issue get` | Single flat issue object |
299
320
 
300
321
  **jq examples:**
301
322
 
302
323
  ```bash
303
- jira-cli issue list --project PROJ | jq '.[].key'
304
- jira-cli search "project = PROJ" | jq '.issues[].key'
305
- jira-cli filter run 12345 | jq '.issues[].status'
324
+ jira-cli issue list --project PROJ | jq '.data[].key'
325
+ jira-cli search "project = PROJ" | jq '.data.issues[].key'
326
+ jira-cli filter run 12345 | jq '.data.issues[].status'
306
327
  ```
307
328
 
308
- ### Flat Issue (default JSON)
329
+ ### Flat Issue (`.data` in default JSON)
309
330
 
310
331
  ```json
311
332
  {
@@ -324,7 +345,7 @@ jira-cli filter run 12345 | jq '.issues[].status'
324
345
  }
325
346
  ```
326
347
 
327
- ### Flat Sprint
348
+ ### Flat Sprint (`.data` in default JSON)
328
349
 
329
350
  ```json
330
351
  {
@@ -337,40 +358,52 @@ jira-cli filter run 12345 | jq '.issues[].status'
337
358
  }
338
359
  ```
339
360
 
340
- ### Error Response (default JSON, written to stderr)
361
+ ### Error Response (default JSON, written to stdout)
341
362
 
342
363
  ```json
343
364
  {
344
- "error": "Jira API error 404: Issue does not exist",
345
- "statusCode": 404,
346
- "errorCode": "NOT_FOUND",
347
- "hint": "Verify the issue key exists and you have permission to view it"
365
+ "ok": false,
366
+ "schema_version": "1.0",
367
+ "error": {
368
+ "code": "E_NOT_FOUND",
369
+ "message": "Jira API error 404: Issue does not exist",
370
+ "details": {
371
+ "status_code": 404,
372
+ "hint": "Verify the resource key/ID exists and you have permission to view it"
373
+ },
374
+ "retryable": false
375
+ }
348
376
  }
349
377
  ```
350
378
 
351
379
  ### Error Codes
352
380
 
353
- | Code | Status | Hint |
354
- |------|--------|------|
355
- | `AUTH_REQUIRED` | 401 | Run `jira-cli login` or set JIRA_HOST and JIRA_TOKEN |
356
- | `FORBIDDEN` | 403 | Check your PAT scope and project permissions |
357
- | `NOT_FOUND` | 404 | Verify the resource key/ID exists |
358
- | `RATE_LIMITED` | 429 | Wait and retry; reduce request frequency |
359
- | `SERVER_ERROR` | 5xx | Jira server error; retry later |
360
- | `NETWORK_ERROR` | — | Check host URL and network connectivity |
361
- | `CONFIG_ERROR` | — | Run `jira-cli login` or set env vars |
381
+ | Code | Status | Retryable | Hint |
382
+ |------|--------|-----------|------|
383
+ | `E_AUTH_REQUIRED` | 401 | false | Run `jira-cli login --host <url> --token <pat>` or set env vars |
384
+ | `E_FORBIDDEN` | 403 | false | Check your PAT scope and project permissions |
385
+ | `E_NOT_FOUND` | 404 | false | Verify the resource key/ID exists |
386
+ | `E_RATE_LIMITED` | 429 | true | Wait and retry with backoff |
387
+ | `E_SERVER` | 5xx | true | Jira server error; retry later |
388
+ | `E_NETWORK` | — | true | Check host URL and network connectivity |
389
+ | `E_CONFIG` | — | false | Run `jira-cli login --host <url> --token <pat>` or set env vars |
390
+ | `E_CONFIRM_REQUIRED` | — | false | Run the same write command with `--dry-run`, then retry with `--confirm <token>` |
391
+ | `E_CONFLICT` | — | false | Re-run `--dry-run`; the token no longer matches the operation |
392
+ | `E_TIMEOUT` | 408 | true | Retry with backoff |
362
393
 
363
394
  ### Exit Codes
364
395
 
365
396
  | Code | Meaning |
366
397
  |------|---------|
367
398
  | 0 | Success |
399
+ | 1 | Generic error |
368
400
  | 2 | Bad arguments |
369
- | 3 | Authentication error |
370
- | 4 | Resource not found |
371
- | 5 | Forbidden |
372
- | 6 | Rate limited |
373
- | 7 | Network/server error |
401
+ | 3 | Resource not found |
402
+ | 4 | Authentication or permission error |
403
+ | 5 | Confirmation token required |
404
+ | 6 | Conflict / stale confirmation token |
405
+ | 7 | Retryable transient error |
406
+ | 8 | Timeout |
374
407
 
375
408
  ## Audit Logging
376
409
 
@@ -384,5 +417,7 @@ All write commands are automatically logged to `~/.jira-cli/audit/` in JSONL for
384
417
  ## Self-Description
385
418
 
386
419
  ```bash
387
- jira-cli reference # Print all commands, subcommands, and flags in structured markdown
420
+ jira-cli reference # Structured JSON command reference
421
+ jira-cli context # Runtime, config, and credential status
422
+ jira-cli doctor # Environment and connectivity checks
388
423
  ```