@fatecannotbealtered-/jira-cli 1.0.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 ADDED
@@ -0,0 +1,43 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.0.0] - 2026-05-03
11
+
12
+ Initial release of jira-cli for Jira Data Center.
13
+
14
+ ### Features
15
+
16
+ - **Jira Data Center only**: Bearer PAT authentication, DC `name`-based user references, `/rest/api/2/` exclusively.
17
+ - **Complete coverage**: issues, sprints, boards, epics, projects, users, filters — CRUD + advanced operations.
18
+ - **AI Agent friendly**:
19
+ - `--json` outputs token-efficient flat format by default; `--raw` returns full Jira API response.
20
+ - `--fields key,summary,status` to output only specified fields.
21
+ - `--quiet` suppresses all non-JSON stdout (clean pipe output).
22
+ - `--dry-run` on all write commands — previews without executing.
23
+ - `--force` skips interactive confirmation prompts.
24
+ - Machine-readable error codes (`errorCode`) and actionable hints (`hint`) in JSON error responses.
25
+ - Semantic exit codes: 0=OK, 2=bad args, 3=auth, 4=not found, 5=forbidden, 6=rate limited, 7=network.
26
+ - `reference` command: structured markdown listing of all commands and flags for AI self-discovery.
27
+ - **Smart retry**: automatic exponential backoff on 429 rate limits and 5xx errors.
28
+ - **Beautiful output**: colored tables with CJK character width support.
29
+ - **Custom fields**: set custom fields during create and edit via `--field "Name=Value"`.
30
+ - **Environment variables**: `JIRA_HOST` and `JIRA_TOKEN` override config file for CI/Agent use.
31
+ - **npm distribution**: `npm install -g @fatecannotbealtered-/jira-cli` with bundled AI Agent Skill.
32
+ - **Cross-platform**: Linux, macOS, Windows (x64 + arm64) via GoReleaser.
33
+ - **E2E test scripts**: Comprehensive PowerShell E2E script (`scripts/e2e-full.ps1`) covering all 55+ commands against a real Jira DC instance, with CSV report output and read-only mode.
34
+ - **Audit logging**: Automatic JSONL audit trail for all write commands (`~/.jira-cli/audit/`), with monthly file rotation and configurable retention (default 3 months). Disable with `JIRA_NO_AUDIT=1`.
35
+
36
+ ### Documentation
37
+
38
+ - Bilingual README (English + Chinese) with CI/Report Card/License/npm badges.
39
+ - SKILL.md with JSON output schemas, error codes, exit codes, and complete flag reference.
40
+ - GitHub PR template for contributors.
41
+
42
+ [Unreleased]: https://github.com/fatecannotbealtered/jira-cli/compare/v1.0.0...HEAD
43
+ [1.0.0]: https://github.com/fatecannotbealtered/jira-cli/releases/tag/v1.0.0
@@ -0,0 +1,56 @@
1
+ # Contributing
2
+
3
+ Thank you for improving jira-cli. This document describes how to build, test, and submit changes.
4
+
5
+ **Note:** This is a side project shared for learning and personal use; maintainers do not offer commercial support or production guarantees�see the readme disclaimer.
6
+
7
+ ## Development setup
8
+
9
+ - Go **1.23+** (see `go.mod`)
10
+ - Optional: **Node.js 16+** if you work on npm install scripts
11
+ - Optional: **golangci-lint** (CI runs it on Linux)
12
+
13
+ Clone and verify:
14
+
15
+ ```bash
16
+ git clone https://github.com/fatecannotbealtered/jira-cli.git
17
+ cd jira-cli
18
+ go mod download
19
+ go test ./...
20
+ go build -o bin/jira-cli ./cmd/jira-cli
21
+ ./bin/jira-cli --help
22
+ ```
23
+
24
+ If `go mod download` is slow, try a regional proxy, for example:
25
+
26
+ ```bash
27
+ # Example (China)
28
+ set GOPROXY=https://goproxy.cn,direct
29
+ ```
30
+
31
+ ## Commands
32
+
33
+ | Goal | Command |
34
+ |------|---------|
35
+ | Run tests (race) | `go test -race ./...` |
36
+ | Format | `gofmt -w .` |
37
+ | Vet | `go vet ./...` |
38
+ | Lint | `golangci-lint run ./...` (or `make lint` on Unix) |
39
+ | Build with version | `make build` (Unix) or `go build -ldflags "-s -w -X github.com/fatecannotbealtered/jira-cli/cmd.version=dev" -o bin/jira-cli.exe ./cmd/jira-cli` (Windows) |
40
+
41
+ CI mirrors `.github/workflows/ci.yml`: tidy modules, `gofmt` check (Linux), golangci-lint, `go vet`, build, `go test -race`, and a `--help` smoke test.
42
+
43
+ ## Pull requests
44
+
45
+ 1. **One logical change per PR** when possible.
46
+ 2. **Tests**: add or update tests for behavior changes in `internal/` or stable CLI contracts.
47
+ 3. **Docs**: update `README.md` / `README_zh.md` if user-facing flags or flows change; add a line to `CHANGELOG.md` under *Unreleased*.
48
+ 4. **Commits**: clear messages; no secrets or real tokens in code or docs.
49
+
50
+ ## AI Agent skill bundle
51
+
52
+ Bundled skills live under `skills/`. After editing, run `jira-cli install-skill` from a built binary (or from repo root with `./skills`) to confirm files copy correctly. npm installs place the binary under `bin/` and skills under `../skills` relative to the binary; the CLI resolves both layouts.
53
+
54
+ ## Security
55
+
56
+ Do not open public issues for undisclosed security vulnerabilities. See [SECURITY.md](SECURITY.md).
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 fatecannotbealtered
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.
package/README.md ADDED
@@ -0,0 +1,397 @@
1
+ # jira-cli
2
+
3
+ [![CI](https://github.com/fatecannotbealtered/jira-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/fatecannotbealtered/jira-cli/actions/workflows/ci.yml)
4
+ [![Go Report Card](https://goreportcard.com/badge/github.com/fatecannotbealtered/jira-cli)](https://goreportcard.com/report/github.com/fatecannotbealtered/jira-cli)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
+ [![npm version](https://img.shields.io/npm/v/@fatecannotbealtered-/jira-cli.svg)](https://www.npmjs.com/package/@fatecannotbealtered-/jira-cli)
7
+
8
+ English | [中文](README_zh.md)
9
+
10
+ Full-featured Jira Data Center CLI for humans and AI Agents. Manage issues, sprints, boards, epics, projects, users, and filters — all from your terminal.
11
+
12
+ Built with Go. Single static binary (small dependency footprint via `go.mod`). No separate runtime to install.
13
+
14
+ [Installation](#installation) · [Authentication](#authentication) · [Commands](#commands) · [JSON Output](#json-output) · [Security](#security) · [Contributing](#contributing) · [Disclaimer](#disclaimer)
15
+
16
+ ## Disclaimer
17
+
18
+ This project is shared for **personal learning, research, and everyday productivity**—not as a product with SLAs. The maintainers do not offer commercial support or make any **fitness-for-production** promise. If you use it at work, that is your call: follow your org's rules. Software is provided "as is," without warranty of any kind.
19
+
20
+ ## Features
21
+
22
+ | Capability | Description |
23
+ |---|---|
24
+ | 🎯 **Complete Coverage** | Issues, Sprints, Boards, Epics, Projects, Users, Filters |
25
+ | 🤖 **AI Friendly** | `--json` flat output (token-efficient), `--quiet`, `--dry-run`, `--force`, `--fields`, `--raw` |
26
+ | ⚡ **Single Binary** | Download and run; no JVM/Node required for the CLI itself |
27
+ | 🔄 **Smart Retry** | Auto-retry on 429 rate limits and 5xx errors with exponential backoff |
28
+ | 🌈 **Beautiful Output** | Colored tables with CJK character support |
29
+ | 🔍 **Powerful Search** | Full JQL support with auto-pagination |
30
+ | 🔧 **Custom Fields** | Set custom fields during create and edit |
31
+ | 🔐 **PAT Auth** | Bearer token authentication (Personal Access Token) |
32
+ | 🌐 **Env Vars** | `JIRA_HOST` and `JIRA_TOKEN` override config file for CI/Agent use |
33
+ | 📋 **Audit Log** | Automatic JSONL audit trail for all write commands with auto-rotation |
34
+
35
+ ## Installation
36
+
37
+ ### Quick start
38
+
39
+ Recommended flow: install the CLI from npm, then install the AI Agent Skill with `npx skills add`.
40
+
41
+ ```bash
42
+ # Install CLI
43
+ npm install -g @fatecannotbealtered-/jira-cli
44
+
45
+ # Install CLI Skill
46
+ npx skills add fatecannotbealtered/jira-cli -y -g
47
+
48
+ # Login and verify
49
+ jira-cli login
50
+ jira-cli doctor
51
+ ```
52
+
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
+
55
+ ### Alternative: Go install
56
+
57
+ ```bash
58
+ go install github.com/fatecannotbealtered/jira-cli/cmd/jira-cli@latest
59
+ ```
60
+
61
+ ### Alternative: Download binary
62
+
63
+ Download from [GitHub Releases](https://github.com/fatecannotbealtered/jira-cli/releases) and add to your PATH.
64
+
65
+ ## Authentication
66
+
67
+ jira-cli supports **Jira Data Center** (private deployments) with **Personal Access Token (PAT)** authentication.
68
+
69
+ ### Interactive login
70
+
71
+ ```bash
72
+ jira-cli login
73
+ # Jira host: https://jira.company.com
74
+ # Personal Access Token (PAT): ****
75
+ # ✔ Logged in as John Doe (johndoe)
76
+
77
+ jira-cli doctor # Verify connectivity
78
+ jira-cli logout # Remove credentials
79
+ ```
80
+
81
+ ### Non-interactive login (CI / AI Agent)
82
+
83
+ ```bash
84
+ jira-cli login --host https://jira.company.com --token <PAT>
85
+ ```
86
+
87
+ ### Environment variables
88
+
89
+ Environment variables take precedence over the config file. This is the recommended approach for CI pipelines and AI Agents:
90
+
91
+ ```bash
92
+ export JIRA_HOST=https://jira.company.com
93
+ export JIRA_TOKEN=<your-personal-access-token>
94
+ jira-cli doctor --json
95
+ ```
96
+
97
+ ### Generating a PAT
98
+
99
+ 1. Log into your Jira Data Center instance
100
+ 2. Go to **Profile** → **Personal Access Tokens**
101
+ 3. Create a new token with appropriate permissions
102
+
103
+ ## Commands
104
+
105
+ ### Issue Management
106
+
107
+ ```bash
108
+ # View
109
+ jira-cli issue get PROJ-123
110
+ jira-cli issue list --project PROJ
111
+ jira-cli issue list --project PROJ --status "In Progress" --assignee me
112
+
113
+ # Create & Edit
114
+ jira-cli issue create --project PROJ --summary "Fix login bug" --type Bug
115
+ jira-cli issue create --project PROJ --summary "Sized story" --field "Story Points=5"
116
+ jira-cli issue edit PROJ-123 --priority High --assignee me
117
+ 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
+
120
+ # Clone
121
+ jira-cli issue clone PROJ-123
122
+ jira-cli issue clone PROJ-123 --summary "New title" --with-links
123
+
124
+ # Status
125
+ jira-cli issue transitions PROJ-123 # List available transitions
126
+ jira-cli issue transition PROJ-123 "Done" # Status name required as argument
127
+
128
+ # Bulk Transition
129
+ jira-cli issue bulk-transition "Done" --issues PROJ-1,PROJ-2,PROJ-3
130
+ jira-cli issue bulk-transition "In Progress" --jql "sprint = 10 AND status = 'To Do'"
131
+
132
+ # Collaboration
133
+ jira-cli issue assign PROJ-123 me # Assign to current user
134
+ jira-cli issue assign PROJ-123 johndoe # Assign by username (DC uses name, not accountId)
135
+ jira-cli issue watch PROJ-123
136
+ jira-cli issue vote PROJ-123
137
+
138
+ # Comments
139
+ jira-cli issue comment add PROJ-123 --body "Fixed in PR #42"
140
+ jira-cli issue comment list PROJ-123
141
+
142
+ # Worklogs
143
+ jira-cli issue worklog add PROJ-123 --time 2h --comment "Debugging"
144
+ jira-cli issue worklog list PROJ-123
145
+
146
+ # Links & Attachments
147
+ jira-cli issue link PROJ-123 --to PROJ-456 --type "blocks"
148
+ jira-cli issue attach PROJ-123 --file ./screenshot.png
149
+ jira-cli issue remote-link PROJ-123 --url https://pr.url --title "PR #42"
150
+ ```
151
+
152
+ ### Search (JQL)
153
+
154
+ ```bash
155
+ jira-cli search "assignee = currentUser() AND status != Done"
156
+ jira-cli search "project = PROJ AND sprint in openSprints()" --all
157
+ jira-cli search "type = Bug AND priority = High" --count
158
+ jira-cli search "project = PROJ" --limit 100 --order-by updated
159
+ ```
160
+
161
+ ### Sprint Management
162
+
163
+ ```bash
164
+ jira-cli sprint list --board 42
165
+ jira-cli sprint active --board 42
166
+ jira-cli sprint create --board 42 --name "Sprint 5" --start-date 2024-02-01 --end-date 2024-02-14
167
+ jira-cli sprint move --sprint 10 --issues PROJ-123,PROJ-124
168
+ jira-cli sprint close --sprint 10 --force
169
+ ```
170
+
171
+ ### Board & Backlog
172
+
173
+ ```bash
174
+ jira-cli board list
175
+ jira-cli board backlog --board 42
176
+ jira-cli board epics --board 42
177
+ ```
178
+
179
+ ### Projects, Users & Filters
180
+
181
+ ```bash
182
+ jira-cli project list
183
+ jira-cli project versions PROJ --unreleased
184
+ jira-cli project fields --custom # List custom fields
185
+ jira-cli user search --query "john"
186
+ jira-cli user me
187
+ jira-cli filter list
188
+ jira-cli filter run <filterId>
189
+ ```
190
+
191
+ ## JSON Output
192
+
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):
194
+
195
+ ```bash
196
+ # Flat JSON (default) — minimal fields, low token cost
197
+ jira-cli issue get PROJ-123 --json
198
+ jira-cli search "project = PROJ" --json | jq '.issues[].key'
199
+
200
+ # Select only the fields you need
201
+ jira-cli issue get PROJ-123 --json --fields key,summary,status,assignee
202
+
203
+ # Raw Jira API response (full nested structure)
204
+ jira-cli issue get PROJ-123 --json --raw
205
+
206
+ # Clean output for scripts (suppress all non-JSON noise)
207
+ jira-cli issue get PROJ-123 --json --quiet
208
+
209
+ # Preview destructive operations without executing
210
+ jira-cli issue delete PROJ-123 --dry-run --json
211
+ ```
212
+
213
+ Error responses include machine-readable error codes and actionable hints:
214
+
215
+ ```json
216
+ {
217
+ "error": "Jira API error 404: Issue does not exist",
218
+ "statusCode": 404,
219
+ "errorCode": "NOT_FOUND",
220
+ "hint": "Verify the issue key exists and you have permission to view it"
221
+ }
222
+ ```
223
+
224
+ Set `NO_COLOR=1` to disable colored output (useful in CI/CD).
225
+
226
+ Run `jira-cli reference` to get a complete listing of all commands and flags in structured markdown.
227
+
228
+ ## Environment Variables
229
+
230
+ | Variable | Description |
231
+ |---|---|
232
+ | `JIRA_HOST` | Jira Data Center host URL (overrides config file) |
233
+ | `JIRA_TOKEN` | Personal Access Token (overrides config file) |
234
+ | `NO_COLOR` | Set to any value to disable colored output ([no-color.org](https://no-color.org)) |
235
+ | `JIRA_CLI_USER_AGENT` | Custom User-Agent string for HTTP requests |
236
+ | `JIRA_NO_AUDIT` | Set to `1` to disable audit logging |
237
+ | `JIRA_AUDIT_RETENTION_MONTHS` | Auto-delete audit files older than N months (default: `3`, `0` = keep forever) |
238
+
239
+ ## Config File
240
+
241
+ Credentials stored at `~/.jira-cli/config.json` (permissions: 0600):
242
+
243
+ ```json
244
+ {
245
+ "host": "https://jira.company.com",
246
+ "token": "your-personal-access-token"
247
+ }
248
+ ```
249
+
250
+ ## Global Flags
251
+
252
+ | Flag | Description |
253
+ |---|---|
254
+ | `--json` | Output as JSON (flat format by default; use `--raw` for full Jira response) |
255
+ | `--force` | Skip interactive confirmation prompts |
256
+ | `--quiet` | Suppress non-JSON stdout output (for scripts and AI Agents) |
257
+ | `--dry-run` | Show what would be done without executing (write commands only) |
258
+
259
+ ### Per-command flags
260
+
261
+ | Flag | Commands | Description |
262
+ |---|---|---|
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`) |
265
+
266
+ ## Troubleshooting
267
+
268
+ | Issue | Solution |
269
+ |---|---|
270
+ | Config not found | Run `jira-cli login` or set `JIRA_HOST` and `JIRA_TOKEN` env vars |
271
+ | Authentication failed | Regenerate PAT in your Jira DC profile settings |
272
+ | Permission denied | Check your PAT scope and project permissions |
273
+ | Resource not found | Verify the issue key or project key exists |
274
+ | Rate limited (429) | The CLI auto-retries; reduce request frequency if persistent |
275
+ | Host must start with https:// | Ensure your host URL includes the `https://` protocol |
276
+
277
+ ## Security
278
+
279
+ - Credentials are stored locally at `~/.jira-cli/config.json` with `0600` file permissions (user-only readable)
280
+ - Config directory is created with `0700` permissions
281
+ - PAT input is hidden during `jira-cli login` (uses terminal secure input)
282
+ - All communication uses HTTPS (host must start with `https://`)
283
+ - No credentials are logged or transmitted to third parties
284
+ - Environment variables `JIRA_HOST` and `JIRA_TOKEN` take precedence over config file
285
+
286
+ > **AI Agent Note:** This tool can be invoked by AI Agents to automate Jira operations. Use `--force` to skip interactive prompts and `--json` for structured output. Set `JIRA_HOST` and `JIRA_TOKEN` environment variables for non-interactive authentication.
287
+
288
+ For vulnerability reports, see [SECURITY.md](SECURITY.md).
289
+
290
+ ## Audit Logging
291
+
292
+ Every write command (create, edit, delete, transition, assign, comment, etc.) is automatically logged to `~/.jira-cli/audit/` in JSONL format — one JSON object per line, one file per month.
293
+
294
+ ```bash
295
+ # Example: view today's audit log
296
+ cat ~/.jira-cli/audit/audit-2026-05.jsonl
297
+
298
+ # Each entry looks like:
299
+ # {"ts":"2026-05-03T14:22:01+08:00","cmd":"issue edit","args":["issue","edit","PROJ-123","--summary","new"],"exit":0,"ms":2031}
300
+ ```
301
+
302
+ ### Configuration
303
+
304
+ | Env var | Default | Description |
305
+ |---------|---------|-------------|
306
+ | `JIRA_NO_AUDIT` | (unset) | Set to `1` to disable audit logging entirely |
307
+ | `JIRA_AUDIT_RETENTION_MONTHS` | `3` | Auto-delete audit files older than N months. Set to `0` to keep forever. |
308
+
309
+ Cleanup runs lazily on each write command — no background process or cron needed.
310
+
311
+ ## E2E Integration Tests
312
+
313
+ A comprehensive E2E test script covers **every jira-cli command** (55+ operations) against a real Jira Data Center instance.
314
+
315
+ ### Quick start
316
+
317
+ ```bash
318
+ # Read-only mode (safe — no data is modified)
319
+ export JIRA_HOST=https://jira.company.com
320
+ export JIRA_TOKEN=<your-pat>
321
+ export JIRA_E2E_MUTATE=0
322
+ pwsh ./scripts/e2e-full.ps1
323
+ ```
324
+
325
+ ### Full test (creates and deletes test issues, filters)
326
+
327
+ ```bash
328
+ pwsh ./scripts/e2e-full.ps1
329
+ ```
330
+
331
+ ### With sprint write tests
332
+
333
+ ```bash
334
+ export JIRA_E2E_SPRINT=1
335
+ pwsh ./scripts/e2e-full.ps1
336
+ ```
337
+
338
+ The script produces:
339
+ - Terminal summary with PASS / FAIL / SKIP counts
340
+ - `scripts/e2e-report.csv` — machine-readable results for CI dashboards
341
+
342
+ ### Environment variables
343
+
344
+ | Variable | Default | Description |
345
+ |---|---|---|
346
+ | `JIRA_HOST` | required | Jira DC host URL |
347
+ | `JIRA_TOKEN` | required | Personal Access Token |
348
+ | `JIRA_CLI_BIN` | `jira-cli` | Path to binary |
349
+ | `JIRA_E2E_PROJECT` | auto-detect | Force a project key |
350
+ | `JIRA_E2E_MUTATE` | `1` | Set `0` for read-only tests |
351
+ | `JIRA_E2E_SPRINT` | `0` | Set `1` for sprint write tests |
352
+ | `JIRA_E2E_CLEANUP` | `1` | Set `0` to keep test resources |
353
+
354
+ ## Project Structure
355
+
356
+ ```
357
+ jira-cli/
358
+ ├── cmd/
359
+ │ ├── jira-cli/
360
+ │ │ └── main.go # Entry point (semantic exit codes)
361
+ │ ├── root.go # Root command, global flags, error handling
362
+ │ ├── login.go # Authentication (PAT-only, non-interactive)
363
+ │ ├── doctor.go # Diagnostics
364
+ │ ├── issue.go # Issue CRUD
365
+ │ ├── issue_*.go # Issue sub-commands
366
+ │ ├── flatten.go # Flat JSON output helpers (issues, sprints)
367
+ │ ├── reference.go # Self-documenting command reference
368
+ │ ├── sprint.go # Sprint management
369
+ │ ├── board.go # Board operations
370
+ │ ├── project.go # Project management
371
+ │ ├── search.go # JQL search
372
+ │ ├── user.go # User operations
373
+ │ ├── filter.go # Saved filters
374
+ │ └── epic.go # Epic operations
375
+ ├── internal/
376
+ │ ├── api/ # Jira REST API v2 client + types
377
+ │ ├── audit/ # Write-operation audit logging (JSONL)
378
+ │ ├── config/ # Config file + env var management
379
+ │ └── output/ # Output formatting (tables, colors, flatten types)
380
+ ├── scripts/
381
+ │ ├── install.js # npm postinstall (downloads binary)
382
+ │ ├── run.js # npm bin wrapper
383
+ │ └── e2e-full.ps1 # Full E2E integration tests (all commands)
384
+ ├── skills/ # AI Agent Skill (bundled for install-skill)
385
+ ├── package.json # npm distribution
386
+ ├── .goreleaser.yml # Release automation
387
+ ├── Makefile # Local development
388
+ └── .github/workflows/ # CI/CD
389
+ ```
390
+
391
+ ## Contributing
392
+
393
+ Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md). Release notes: [CHANGELOG.md](CHANGELOG.md).
394
+
395
+ ## License
396
+
397
+ MIT © fatecannotbealtered
package/SECURITY.md ADDED
@@ -0,0 +1,28 @@
1
+ # Security
2
+
3
+ ## Supported versions
4
+
5
+ Security fixes are applied to the latest minor release on the default branch (`main`). Release binaries are published via GitHub Releases and the npm package `@fatecannotbealtered-/jira-cli`.
6
+
7
+ ## Reporting a vulnerability
8
+
9
+ Please **do not** file a public GitHub issue for undisclosed security vulnerabilities.
10
+
11
+ Instead, report privately via [GitHub Security Advisories](https://github.com/fatecannotbealtered/jira-cli/security/advisories/new) for this repository, or contact the maintainers through the contact options on the repository homepage.
12
+
13
+ Include:
14
+
15
+ - Description of the issue and impact
16
+ - Steps to reproduce (if safe to share)
17
+ - Affected versions or install methods (binary / npm / `go install`)
18
+
19
+ You should receive an acknowledgment as capacity allows. Thank you for helping keep users safe.
20
+
21
+ ## Credential handling (design)
22
+
23
+ - Credentials are stored only in `~/.jira-cli/config.json` with file mode `0600` and directory `0700`.
24
+ - API tokens are read with hidden input in interactive terminals.
25
+ - Traffic is HTTPS-only to the configured Jira Data Center host (host must start with `https://`).
26
+ - Environment variables `JIRA_HOST` and `JIRA_TOKEN` take precedence over config file; prefer them in CI/Agent workflows to avoid persisting credentials on disk.
27
+
28
+ Review these assumptions when integrating jira-cli into automation or AI agent workflows.
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@fatecannotbealtered-/jira-cli",
3
+ "version": "1.0.0",
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
+ "keywords": [
6
+ "jira",
7
+ "cli",
8
+ "atlassian",
9
+ "ai-agent",
10
+ "devtools",
11
+ "sprint",
12
+ "issue-tracker",
13
+ "openclaw"
14
+ ],
15
+ "author": "guosong6886@gmail.com",
16
+ "homepage": "https://github.com/fatecannotbealtered/jira-cli#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/fatecannotbealtered/jira-cli/issues"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/fatecannotbealtered/jira-cli.git"
23
+ },
24
+ "license": "MIT",
25
+ "bin": {
26
+ "jira-cli": "scripts/run.js"
27
+ },
28
+ "scripts": {
29
+ "postinstall": "node scripts/install.js"
30
+ },
31
+ "files": [
32
+ "scripts/install.js",
33
+ "scripts/run.js",
34
+ "skills/",
35
+ "CHANGELOG.md",
36
+ "CONTRIBUTING.md",
37
+ "SECURITY.md"
38
+ ],
39
+ "os": [
40
+ "darwin",
41
+ "linux",
42
+ "win32"
43
+ ],
44
+ "cpu": [
45
+ "x64",
46
+ "arm64"
47
+ ],
48
+ "engines": {
49
+ "node": ">=16"
50
+ }
51
+ }
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ const crypto = require("crypto");
7
+ const { execFileSync } = require("child_process");
8
+ const os = require("os");
9
+
10
+ const VERSION = require("../package.json").version;
11
+ const REPO = "fatecannotbealtered/jira-cli";
12
+ const NAME = "jira-cli";
13
+
14
+ const PLATFORM_MAP = {
15
+ darwin: "darwin",
16
+ linux: "linux",
17
+ win32: "windows",
18
+ };
19
+
20
+ const ARCH_MAP = {
21
+ x64: "amd64",
22
+ arm64: "arm64",
23
+ };
24
+
25
+ const platform = PLATFORM_MAP[process.platform];
26
+ let arch = ARCH_MAP[process.arch];
27
+
28
+ // Windows ARM64: fall back to amd64 (runs via emulation)
29
+ if (process.platform === "win32" && process.arch === "arm64") {
30
+ console.log("Windows ARM64 detected, falling back to x64 binary (runs via emulation)");
31
+ arch = "amd64";
32
+ }
33
+
34
+ if (!platform || !arch) {
35
+ console.error(`Unsupported platform: ${process.platform}-${process.arch}`);
36
+ console.error(`\nManually download from:\n https://github.com/${REPO}/releases`);
37
+ process.exit(1);
38
+ }
39
+
40
+ const isWindows = process.platform === "win32";
41
+ const ext = isWindows ? ".zip" : ".tar.gz";
42
+ const archiveName = `${NAME}-${VERSION}-${platform}-${arch}${ext}`;
43
+ const GITHUB_URL = `https://github.com/${REPO}/releases/download/v${VERSION}/${archiveName}`;
44
+
45
+ const binDir = path.join(__dirname, "..", "bin");
46
+ const dest = path.join(binDir, NAME + (isWindows ? ".exe" : ""));
47
+
48
+ fs.mkdirSync(binDir, { recursive: true });
49
+
50
+ function download(url, destPath) {
51
+ const args = [
52
+ "--fail", "--location", "--silent", "--show-error",
53
+ "--connect-timeout", "15", "--max-time", "120",
54
+ "--output", destPath, url,
55
+ ];
56
+ if (isWindows) {
57
+ args.unshift("--ssl-revoke-best-effort");
58
+ }
59
+ execFileSync("curl", args, { stdio: ["ignore", "ignore", "pipe"] });
60
+ }
61
+
62
+ function verifyChecksum(filePath, expectedHash) {
63
+ const fileBuffer = fs.readFileSync(filePath);
64
+ const hash = crypto.createHash("sha256").update(fileBuffer).digest("hex");
65
+ if (hash !== expectedHash) {
66
+ throw new Error(
67
+ `Checksum mismatch!\n Expected: ${expectedHash}\n Actual: ${hash}`
68
+ );
69
+ }
70
+ }
71
+
72
+ function install() {
73
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "jira-cli-"));
74
+ const archivePath = path.join(tmpDir, archiveName);
75
+ const checksumURL = `https://github.com/${REPO}/releases/download/v${VERSION}/checksums.txt`;
76
+ const checksumPath = path.join(tmpDir, "checksums.txt");
77
+
78
+ try {
79
+ console.log(`Downloading ${NAME} v${VERSION} for ${platform}-${arch}...`);
80
+ download(GITHUB_URL, archivePath);
81
+
82
+ // Verify checksum
83
+ try {
84
+ download(checksumURL, checksumPath);
85
+ const checksumContent = fs.readFileSync(checksumPath, "utf8");
86
+ const line = checksumContent
87
+ .split("\n")
88
+ .find((l) => l.includes(archiveName));
89
+ if (line) {
90
+ const expectedHash = line.trim().split(/\s+/)[0];
91
+ verifyChecksum(archivePath, expectedHash);
92
+ console.log("✔ Checksum verified");
93
+ } else {
94
+ console.warn("Warning: archive not found in checksums.txt, skipping verification");
95
+ }
96
+ } catch (checksumErr) {
97
+ if (checksumErr.message.includes("Checksum mismatch")) {
98
+ throw checksumErr;
99
+ }
100
+ console.warn("Warning: could not verify checksum —", checksumErr.message);
101
+ }
102
+
103
+ // Extract binary
104
+ if (isWindows) {
105
+ execFileSync("powershell", [
106
+ "-Command",
107
+ `Expand-Archive -Path '${archivePath}' -DestinationPath '${tmpDir}' -Force`,
108
+ ], { stdio: "ignore" });
109
+ } else {
110
+ execFileSync("tar", ["-xzf", archivePath, "-C", tmpDir], {
111
+ stdio: "ignore",
112
+ });
113
+ }
114
+
115
+ const binaryName = NAME + (isWindows ? ".exe" : "");
116
+ const extractedBinary = path.join(tmpDir, binaryName);
117
+
118
+ fs.copyFileSync(extractedBinary, dest);
119
+ if (!isWindows) {
120
+ fs.chmodSync(dest, 0o755);
121
+ }
122
+ console.log(`✔ ${NAME} v${VERSION} installed successfully`);
123
+ } finally {
124
+ fs.rmSync(tmpDir, { recursive: true, force: true });
125
+ }
126
+ }
127
+
128
+ try {
129
+ install();
130
+ } catch (err) {
131
+ console.error(`Failed to install ${NAME}:`, err.message);
132
+ console.error(
133
+ `\nManually download from:\n https://github.com/${REPO}/releases\n`
134
+ );
135
+ process.exit(1);
136
+ }
package/scripts/run.js ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const { execFileSync } = require("child_process");
5
+ const path = require("path");
6
+
7
+ const ext = process.platform === "win32" ? ".exe" : "";
8
+ const bin = path.join(__dirname, "..", "bin", "jira-cli" + ext);
9
+
10
+ try {
11
+ execFileSync(bin, process.argv.slice(2), { stdio: "inherit" });
12
+ } catch (e) {
13
+ if (e.code === "ENOENT") {
14
+ console.error("Binary not found. Run 'npm install -g @fatecannotbealtered-/jira-cli' to reinstall.");
15
+ }
16
+ process.exit(e.status || 1);
17
+ }
@@ -0,0 +1,323 @@
1
+ ---
2
+ name: jira-cli
3
+ description: Full Jira Data Center control from the terminal. Manage issues, sprints, boards, epics, projects, users, and filters. Use --json flag for machine-readable output when parsing results programmatically.
4
+ metadata: {"openclaw":{"emoji":"🎯","requires":{"bins":["jira-cli"]}}}
5
+ ---
6
+
7
+ # jira-cli
8
+
9
+ Jira Data Center CLI for humans and AI Agents. Supports **Jira DC only** (self-hosted), not Jira Cloud.
10
+
11
+ ## Prerequisites
12
+
13
+ Before using any command, authenticate with a Jira DC instance. Follow these steps in order:
14
+
15
+ 1. Ask the user for their Jira DC URL (e.g. `https://jira.company.com`). It must start with `https://`.
16
+ 2. Ask the user for a **Personal Access Token (PAT)**. If they don't have one, guide them:
17
+ "Log in to your Jira DC → click your profile avatar → Personal Access Tokens → Create token."
18
+ 3. Run `jira-cli login --host <URL> --token <PAT>` to save credentials.
19
+ 4. Run `jira-cli doctor --json` to verify connectivity. If `authValid` is `true`, you're ready.
20
+
21
+ **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.
22
+
23
+ **Always use `--json` flag when parsing output.** Without it, output is human-formatted and not suitable for programmatic use.
24
+
25
+ ## Safety
26
+
27
+ - **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.
28
+ - **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`.
29
+ - **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.
30
+ - All write operations are recorded in `~/.jira-cli/audit/` for traceability.
31
+
32
+ ## Issue Management
33
+
34
+ ```bash
35
+ # View issues (flat JSON by default — token-efficient)
36
+ jira-cli issue get PROJ-123 --json
37
+ jira-cli issue get PROJ-123 --json --fields key,summary,status,assignee # Only specific fields
38
+ jira-cli issue get PROJ-123 --json --raw # Full Jira API response
39
+ jira-cli issue list --project PROJ --json
40
+ jira-cli issue list --project PROJ --status "In Progress" --assignee me --json
41
+ jira-cli issue list --project PROJ --type Bug --priority High --limit 20 --json
42
+
43
+ # Create and edit
44
+ jira-cli issue create --project PROJ --summary "Fix login bug" --type Bug --json
45
+ jira-cli issue create --project PROJ --summary "New feature" --type Story --assignee me --priority High --json
46
+ jira-cli issue create --project PROJ --summary "Sized story" --type Story --field "Story Points=5" --json
47
+ jira-cli issue edit PROJ-123 --summary "Updated summary" --priority Medium
48
+ jira-cli issue edit PROJ-123 --field "Story Points=8" --field "Team=Backend"
49
+ jira-cli issue delete PROJ-123 --force # Skip confirmation prompt
50
+
51
+ # Clone an issue
52
+ jira-cli issue clone PROJ-123 --json # Clone with default summary
53
+ jira-cli issue clone PROJ-123 --summary "New title" --json # Clone with custom summary
54
+ jira-cli issue clone PROJ-123 --with-links --json # Clone with issue links
55
+
56
+ # Status transitions
57
+ jira-cli issue transitions PROJ-123 --json # List available transitions
58
+ jira-cli issue transition PROJ-123 "In Progress" # Transition to status (name required)
59
+ jira-cli issue transition PROJ-123 "Done" --json
60
+
61
+ # Bulk transition
62
+ jira-cli issue bulk-transition "Done" --issues PROJ-1,PROJ-2,PROJ-3 --json
63
+ jira-cli issue bulk-transition "In Progress" --jql "project = PROJ AND sprint = 10 AND status = 'To Do'" --json
64
+
65
+ # Assignment and watching
66
+ jira-cli issue assign PROJ-123 me # Assign to current user
67
+ jira-cli issue assign PROJ-123 johndoe # Assign by username (DC uses name, not accountId)
68
+ jira-cli issue unassign PROJ-123
69
+ jira-cli issue watch PROJ-123
70
+ jira-cli issue unwatch PROJ-123
71
+ jira-cli issue watchers PROJ-123 --json
72
+ jira-cli issue vote PROJ-123
73
+ jira-cli issue unvote PROJ-123
74
+
75
+ # Comments
76
+ jira-cli issue comment add PROJ-123 --body "Fixed in PR #42" --json
77
+ jira-cli issue comment list PROJ-123 --json
78
+ jira-cli issue comment delete PROJ-123 --id <commentId>
79
+
80
+ # Worklogs
81
+ jira-cli issue worklog add PROJ-123 --time 2h --comment "Debugging session" --json
82
+ jira-cli issue worklog add PROJ-123 --time 1h30m --started "2024-01-15T10:00:00.000+0000"
83
+ jira-cli issue worklog list PROJ-123 --json
84
+
85
+ # Links
86
+ jira-cli issue link-types --json # List available link types
87
+ jira-cli issue link PROJ-123 --to PROJ-456 --type "blocks"
88
+ jira-cli issue unlink <linkId>
89
+ jira-cli issue remote-link PROJ-123 --url https://pr.url --title "PR #42"
90
+ jira-cli issue remote-links PROJ-123 --json
91
+
92
+ # Attachments
93
+ jira-cli issue attach PROJ-123 --file ./screenshot.png
94
+ jira-cli issue attachments PROJ-123 --json
95
+ ```
96
+
97
+ ## Search (JQL)
98
+
99
+ ```bash
100
+ # Basic search
101
+ jira-cli search "assignee = currentUser() AND status != Done" --json
102
+ jira-cli search "project = PROJ AND sprint in openSprints()" --json
103
+
104
+ # Advanced options
105
+ jira-cli search "project = PROJ" --limit 100 --json
106
+ jira-cli search "project = PROJ" --all --json # Fetch ALL results (auto-paginate)
107
+ jira-cli search "project = PROJ" --count # Only show total count
108
+ jira-cli search "project = PROJ" --order-by updated --json
109
+ jira-cli search "type = Bug AND priority = High" --fields key,summary,status --json
110
+ ```
111
+
112
+ ## Sprint Management
113
+
114
+ ```bash
115
+ jira-cli board list --json # Find board IDs first
116
+ jira-cli sprint list --board 42 --json
117
+ jira-cli sprint list --board 42 --state active --json
118
+ jira-cli sprint active --board 42 --json # Active sprint + issues
119
+ jira-cli sprint issues --sprint 10 --json
120
+ jira-cli sprint create --board 42 --name "Sprint 5" --start-date 2024-02-01 --end-date 2024-02-14 --json
121
+ jira-cli sprint update --sprint 10 --goal "Complete payment refactor"
122
+ jira-cli sprint move --sprint 10 --issues PROJ-123,PROJ-124,PROJ-125
123
+ jira-cli sprint close --sprint 10 --force # --force skips confirmation
124
+ ```
125
+
126
+ ## Board & Backlog
127
+
128
+ ```bash
129
+ jira-cli board list --json
130
+ jira-cli board list --project PROJ --type scrum --json
131
+ jira-cli board get --board 42 --json
132
+ jira-cli board backlog --board 42 --json
133
+ jira-cli board epics --board 42 --json
134
+ jira-cli board sprints --board 42 --state active --json
135
+ ```
136
+
137
+ ## Epic Management
138
+
139
+ ```bash
140
+ jira-cli epic list --board 42 --json
141
+ jira-cli epic list --board 42 --done --json # Completed epics only
142
+ jira-cli epic issues PROJ-1 --board 42 --json
143
+ ```
144
+
145
+ ## Project Management
146
+
147
+ ```bash
148
+ jira-cli project list --json
149
+ jira-cli project list --type software --json
150
+ jira-cli project get PROJ --json
151
+ jira-cli project components PROJ --json
152
+ jira-cli project versions PROJ --json
153
+ jira-cli project versions PROJ --unreleased --json
154
+ jira-cli project issue-types PROJ --json
155
+ jira-cli project fields --json # List all fields (system + custom)
156
+ jira-cli project fields --custom --json # List custom fields only
157
+ ```
158
+
159
+ ## User Search
160
+
161
+ ```bash
162
+ jira-cli user me --json # Current user info
163
+ jira-cli user search --query "john" --json
164
+ jira-cli user search --query "john" --assignable --project PROJ --json
165
+ ```
166
+
167
+ ## Filters
168
+
169
+ ```bash
170
+ jira-cli filter list --json
171
+ jira-cli filter get <filterId> --json
172
+ jira-cli filter create --name "My Bugs" --jql "assignee = me AND type = Bug" --json
173
+ jira-cli filter run <filterId> --json
174
+ jira-cli filter delete <filterId>
175
+ ```
176
+
177
+ ## Workflow Examples
178
+
179
+ ### Find and update an issue
180
+ ```bash
181
+ # 1. Search for issues
182
+ jira-cli search "project = PROJ AND assignee = me AND status = 'In Progress'" --json
183
+
184
+ # 2. Get issue details
185
+ jira-cli issue get PROJ-123 --json
186
+
187
+ # 3. Check available transitions
188
+ jira-cli issue transitions PROJ-123 --json
189
+
190
+ # 4. Transition to Done
191
+ jira-cli issue transition PROJ-123 "Done"
192
+
193
+ # 5. Add a comment
194
+ jira-cli issue comment add PROJ-123 --body "Completed and deployed to staging"
195
+ ```
196
+
197
+ ### Sprint planning workflow
198
+ ```bash
199
+ # 1. Find the board
200
+ jira-cli board list --json
201
+
202
+ # 2. Check active sprint
203
+ jira-cli sprint active --board 42 --json
204
+
205
+ # 3. View backlog
206
+ jira-cli board backlog --board 42 --json
207
+
208
+ # 4. Create next sprint
209
+ jira-cli sprint create --board 42 --name "Sprint 6" --start-date 2024-02-15 --end-date 2024-02-28 --json
210
+
211
+ # 5. Move issues to sprint
212
+ jira-cli sprint move --sprint 11 --issues PROJ-200,PROJ-201,PROJ-202
213
+ ```
214
+
215
+ ## Guardrails
216
+
217
+ - Always run `jira-cli doctor --json` to verify auth before bulk operations
218
+ - `issue delete` requires typing the issue key to confirm. Use `--force` to skip confirmation in automated workflows
219
+ - `sprint close` is irreversible. Use `--force` to skip confirmation
220
+ - Use `--json` flag when parsing output in scripts or AI workflows
221
+ - Use `--dry-run` to preview what a write command would do without executing it
222
+ - Use `--quiet` with `--json` to suppress all non-JSON output (clean pipe-friendly output)
223
+ - `issue transition` requires the status name as the second argument (no interactive selection)
224
+ - When searching for usernames to use with `issue assign`, use `user search --query <name> --json` first
225
+ - DC uses **username** (not accountId) for user references. Use `jira-cli user me --json` to find your username
226
+
227
+ ## Global Flags
228
+
229
+ - `--json` — Output as JSON (machine-readable, flat format by default)
230
+ - `--force` — Skip interactive confirmation prompts (for CI/Agent automation)
231
+ - `--quiet` — Suppress non-JSON stdout output (ideal for scripts and AI Agents)
232
+ - `--dry-run` — Show what would be done without executing (write commands only)
233
+
234
+ ## Output Control Flags
235
+
236
+ These flags are available on read commands (`issue get`, `issue list`, `search`, `sprint list`, `sprint issues`):
237
+
238
+ - `--raw` — Return the full raw Jira API response instead of the token-efficient flat format
239
+ - `--fields key,summary,status` — Output only the specified fields (flat JSON mode only)
240
+
241
+ ## JSON Output Schemas
242
+
243
+ ### Flat Issue (default with --json)
244
+
245
+ ```json
246
+ {
247
+ "key": "PROJ-123",
248
+ "summary": "Fix login bug",
249
+ "status": "In Progress",
250
+ "type": "Bug",
251
+ "assignee": "johndoe",
252
+ "reporter": "janedoe",
253
+ "priority": "High",
254
+ "created": "2024-01-15T10:30:00.000+0000",
255
+ "updated": "2024-01-16T14:20:00.000+0000",
256
+ "labels": "backend,urgent",
257
+ "component": "auth",
258
+ "parent": "PROJ-100"
259
+ }
260
+ ```
261
+
262
+ ### Flat Sprint
263
+
264
+ ```json
265
+ {
266
+ "id": 42,
267
+ "name": "Sprint 5",
268
+ "state": "active",
269
+ "startDate": "2024-02-01",
270
+ "endDate": "2024-02-14",
271
+ "goal": "Complete payment module"
272
+ }
273
+ ```
274
+
275
+ ### Error Response (with --json)
276
+
277
+ ```json
278
+ {
279
+ "error": "Jira API error 404: Issue does not exist",
280
+ "statusCode": 404,
281
+ "errorCode": "NOT_FOUND",
282
+ "hint": "Verify the issue key exists and you have permission to view it"
283
+ }
284
+ ```
285
+
286
+ ### Error Codes
287
+
288
+ | Code | Status | Hint |
289
+ |------|--------|------|
290
+ | `AUTH_REQUIRED` | 401 | Run `jira-cli login` or set JIRA_HOST and JIRA_TOKEN |
291
+ | `FORBIDDEN` | 403 | Check your PAT scope and project permissions |
292
+ | `NOT_FOUND` | 404 | Verify the resource key/ID exists |
293
+ | `RATE_LIMITED` | 429 | Wait and retry; reduce request frequency |
294
+ | `SERVER_ERROR` | 5xx | Jira server error; retry later |
295
+ | `NETWORK_ERROR` | — | Check host URL and network connectivity |
296
+ | `CONFIG_ERROR` | — | Run `jira-cli login` or set env vars |
297
+
298
+ ### Exit Codes
299
+
300
+ | Code | Meaning |
301
+ |------|---------|
302
+ | 0 | Success |
303
+ | 2 | Bad arguments |
304
+ | 3 | Authentication error |
305
+ | 4 | Resource not found |
306
+ | 5 | Forbidden |
307
+ | 6 | Rate limited |
308
+ | 7 | Network/server error |
309
+
310
+ ## Audit Logging
311
+
312
+ All write commands are automatically logged to `~/.jira-cli/audit/` in JSONL format (one file per month). Each entry records the command, arguments, exit code, and duration.
313
+
314
+ | Env var | Default | Description |
315
+ |---------|---------|-------------|
316
+ | `JIRA_NO_AUDIT` | (unset) | Set `1` to disable audit logging |
317
+ | `JIRA_AUDIT_RETENTION_MONTHS` | `3` | Auto-delete files older than N months (`0` = keep forever) |
318
+
319
+ ## Self-Description
320
+
321
+ ```bash
322
+ jira-cli reference # Print all commands, subcommands, and flags in structured markdown
323
+ ```