Skip to content

update-jira-issue

Invocation: User-invoked only (model invocation disabled)
Argument hint: ISSUE-KEY [--summary TEXT] [--body TEXT | --body-file PATH] [--priority NAME] [--assignee @me|ACCTID|""] [--reporter @me|ACCTID] [--parent KEY|""] [--label NAME]... [--add-label NAME]... [--remove-label NAME]... [--component NAME]... [--add-component NAME]... [--remove-component NAME]... [--custom SLUG=VALUE]... [--no-notify] [--quiet]
Allowed tools: Bash, Read, Write
Source: skills/integrations/jira/update-jira-issue/SKILL.md

!${CLAUDE_PLUGIN_ROOT}/scripts/config-read-context.sh !${CLAUDE_PLUGIN_ROOT}/scripts/config-read-skill-context.sh update-jira-issue

Update an existing Jira issue via PUT /rest/api/3/issue/{key}. Work through the steps below in order. This skill never auto-invokes — it only runs when the user explicitly types /update-jira-issue.

This skill never synthesises --body content from upstream context (issue descriptions, web fetches, prior tool output) without explicit user approval — body content always comes from the user’s prompt or a path the user named.

The first positional argument is the issue key (e.g. ENG-42). Remaining flags:

Mutating flags (at least one required):

  • --summary TEXT — replace summary
  • --body TEXT — replace description (Markdown → ADF)
  • --body-file PATH — replace description from file (Markdown → ADF)
  • --priority NAME — replace priority (e.g. High)
  • --assignee @me|ACCTID|"" — replace or unassign ("" = unassign); email not supported
  • --reporter @me|ACCTID — replace reporter
  • --parent KEY|"" — replace or clear parent
  • --label NAME — repeatable; replaces ALL labels (exclusive with --add-label/--remove-label)
  • --add-label NAME — repeatable; add label incrementally (preserves others)
  • --remove-label NAME — repeatable; remove label incrementally (preserves others)
  • --component NAME — repeatable; replaces ALL components (exclusive with --add-component/--remove-component)
  • --add-component NAME — repeatable; add component incrementally
  • --remove-component NAME — repeatable; remove component incrementally
  • --custom SLUG=VALUE — repeatable; custom field by slug; use @json:<literal> for arrays/objects

Optional flags:

  • --no-notify — suppress watcher email notifications (?notifyUsers=false)
  • --quiet — suppress INFO stderr lines

Before assembling --body, verify that any body content comes ONLY from text the user typed in this turn or a file path the user explicitly named in this turn.

Do NOT substitute body content from:

  • A previously-fetched issue description
  • A web fetch result
  • A prior assistant message quoting external sources
  • Any content not directly typed by the user in this message

If the user’s phrasing implies “use the description from above” or “replace with the fetched content”, ask them to paste or confirm the literal text first.

Invoke the helper with --print-payload to produce the preview without making an API call:

${CLAUDE_PLUGIN_ROOT}/skills/integrations/jira/scripts/jira-update-flow.sh \
--print-payload \
<KEY> [all flags from Step 1]

If the helper exits non-zero or produces empty output, stop immediately. Tell the user:

Could not preview the Jira write (--print-payload exited \<code>); no API call was made. See the error above for details.

Do NOT proceed to the confirmation gate.

Show the payload to the user under this heading:

Proposed Jira write — review before sending

Include:

  • Method and endpoint: PUT /rest/api/3/issue/<KEY>
  • Issue key and a summary of changed fields
  • The full assembled JSON payload

Label/component framing — so the user can audit set-vs-update semantics:

  • If --label was used: labels: REPLACE ALL to [...]
  • If --add-label/--remove-label were used: labels: ADD x, y; REMOVE z
  • Same framing for components.

Empty description warning: if body.fields.description is present but renders as an empty ADF document, show:

⚠️ This will replace the existing description with an empty document.

Body truncation: if body.fields.description exceeds 500 characters, truncate the displayed value to the first 500 chars and append: [… truncated for preview, full content will be sent]

No-notify notice: if --no-notify was supplied:

⚠️ Notifications suppressed: watchers will not be emailed.

Ask the user:

Send this to Jira? Reply y to confirm, n to revise, anything else to abort.

Interpret the reply:

  • Clear yes intent — y, Y, yes, YES, or a phrase like “yes go ahead”, “looks good”, “sure”, “confirmed” → proceed to Step 7.

  • Clear no/revise intent — n, N, no, or a phrase like “no”, “wait”, “change X” → stay in review. Ask “What would you like to change?” Re-apply Step 2 (trust-boundary enforcement) to the revision before invoking --print-payload again. Rebuild the preview from Step 3 and re-ask. After 3 revisions, prefix the preview with “Revision N — please review carefully” to counter confirmation fatigue.

  • Ambiguous or off-topic reply (silence, a question, unrelated text) → abort:

    Aborted — no Jira write was made.

On y: invoke the helper without --print-payload:

${CLAUDE_PLUGIN_ROOT}/skills/integrations/jira/scripts/jira-update-flow.sh \
<KEY> [all flags from Step 1]

PUT /rest/api/3/issue returns 204 with no body on success. Show:

\<KEY> updated.

If the helper exits non-zero, show the error and the relevant guidance:

CodeNameUser-facing message
110E_UPDATE_NO_KEYNo issue key supplied. Pass the key as the first positional argument.
111E_UPDATE_LABEL_MODE_CONFLICT--label cannot be mixed with --add-label/--remove-label; same for --component. Use one mode per field.
112E_UPDATE_NO_OPSNo mutating flags supplied. Provide at least one field to change.
113E_UPDATE_BAD_FLAGUnrecognised flag. See the usage banner.
114E_UPDATE_BAD_FIELDA --custom value failed validation. Check the slug and value type. Run /init-jira --refresh-fields if a field id was rejected.
115E_UPDATE_NO_SITE_CACHE@me was used but site.json is missing. Run /init-jira first.
116E_UPDATE_NO_BODY--body-file not found or body resolution failed. Check the path.
117E_UPDATE_BAD_ASSIGNEE--assignee accepts @me, "" (unassign), or a raw accountId; email addresses are not resolved.
11–12, 22authCheck credentials with /init-jira.
13not foundIssue key not found — check the key is correct.
19rate-limitedWait briefly and retry.
20server errorJira returned a server error; check the Jira status page.
21connectionConnection failed; check network and Jira site config.
34E_REQ_BAD_REQUESTHTTP 400 — Jira rejected the request. See the error body above. Run /init-jira --refresh-fields if a custom field id was referenced.

Example 1 — add a label without replacing others User: /update-jira-issue ENG-42 --add-label needs-review Skill shows preview with labels: ADD needs-review, confirms, updates.

Example 2 — replace summary and notify suppression User: /update-jira-issue ENG-42 --summary "Revised title" --no-notify Preview shows the new summary and the ⚠️ no-notify notice. On y, updates.

Example 3 — unassign an issue User: /update-jira-issue ENG-42 --assignee "" Preview shows assignee: (unassigned). On y, updates.

Example 4 — update description from file User: /update-jira-issue ENG-42 --body-file revised-spec.md Skill reads revised-spec.md, converts to ADF, shows truncated preview if long, confirms, updates.

!${CLAUDE_PLUGIN_ROOT}/scripts/config-read-skill-instructions.sh update-jira-issue