jira-rest-v3
v1.1.0通过 Jira Cloud REST API v3 执行日常任务:搜索、创建、更新、分配事务;管理评论与工作日志;处理看板、冲刺及工作流转换。
Installation
File: skills/jira-rest-v3/SKILL.md
openClaw Skill — Jira Daily Work via ATREST (Jira Cloud REST API v3 + Jira Software Agile API)
What this skill is for
Use this skill to perform everyday Jira work from openClaw: - find and triage issues (JQL search) - read and update issues (fields, assignee, workflow transition) - create issues - manage comments (list, add, update, delete) - log time (worklogs) - work with boards, backlog, and sprints (Jira Software Agile API)
This skill assumes Jira Cloud.
Most important rule for openClaw
When a user explicitly asks for Jira work, or when a task clearly requires Jira data, do not merely describe the REST API.
You MUST do all of the following: 1. map the user request to a concrete Jira REST endpoint 2. build the final HTTP method + URL + query + headers + body 3. execute a real CLI HTTP call from the current OS environment 4. parse the JSON response 5. report the result back to the user in a concise human-readable format
If the environment is Linux, prefer curl.
If the environment is Windows, prefer either curl.exe or PowerShell Invoke-RestMethod.
Never stop at “the API endpoint would be …”. The skill is only considered applied when the actual CLI request is made.
Required environment variables (openclaw.json -> "env")
All variables MUST use the ATREST_ prefix.
Jira site + authentication
ATREST_JIRA_BASE_URL- Example:
https://your-domain.atlassian.net - Do NOT include a trailing slash.
ATREST_JIRA_AUTH_MODEbasic(recommended for scripts) orbearerATREST_JIRA_EMAIL- Required when
ATREST_JIRA_AUTH_MODE=basic ATREST_JIRA_API_TOKEN- Required when
ATREST_JIRA_AUTH_MODE=basic ATREST_JIRA_BEARER_TOKEN- Required when
ATREST_JIRA_AUTH_MODE=bearer ATREST_JIRA_USER_AGENT- Example:
openClaw-jira-atrest/1.0
Defaults (optional but practical)
ATREST_JIRA_DEFAULT_PROJECT_KEYATREST_JIRA_DEFAULT_ISSUE_TYPE- Example:
Task,Bug,Story ATREST_JIRA_DEFAULT_BOARD_IDATREST_JIRA_DEFAULT_MAX_RESULTS- Example:
50 ATREST_JIRA_DEFAULT_FIELDS- Comma-separated list for search/read, e.g.
summary,status,assignee,priority,updated
Resilience (optional)
ATREST_HTTP_TIMEOUT_MS(e.g.30000)ATREST_HTTP_RETRY_MAX(e.g.3)ATREST_HTTP_RETRY_BACKOFF_MS(e.g.1000)
See also: refs/openclaw_env_example.json.
API base paths (two families)
1) Jira Cloud Platform REST API v3 (issues, comments, projects, users, worklogs, …)
- Base: ${ATREST_JIRA_BASE_URL}/rest/api/3
2) Jira Software Agile REST API (boards, sprints, backlog, ranking, …)
- Base: ${ATREST_JIRA_BASE_URL}/rest/agile/1.0
When selecting an endpoint, always choose the correct base family first. - issue, comment, worklog, project, user => Platform v3 - board, backlog, sprint => Agile API
Authentication rules (must follow)
If AUTH_MODE = basic
- Use HTTP Basic Auth with email + API token.
- Either:
- set
Authorization: Basic <base64(email:apiToken)>, or - use the HTTP client’s built-in basic auth feature.
If AUTH_MODE = bearer
- Set
Authorization: Bearer ${ATREST_JIRA_BEARER_TOKEN}
Never print secrets, never echo tokens into logs, never store tokens in repo.
Rich-text fields (ADF)
Jira Cloud v3 uses Atlassian Document Format (ADF) for:
- issue description, environment, and textarea custom fields
- comment body
- worklog comment
When the user provides plain text, wrap it into minimal ADF.
See refs/jira-json-quickref.md#adf-minimal.
CLI execution contract (this is the part openClaw must follow)
For every Jira command, execute the request through the OS shell.
Mandatory workflow
- Verify required environment variables exist.
- Decide whether the endpoint belongs to Platform v3 or Agile API.
- Build the final path.
- Add query parameters.
- Build headers:
Accept: application/jsonContent-Type: application/jsonfor requests with JSON bodyUser-Agent: ${ATREST_JIRA_USER_AGENT}if setAuthorization: ...according to auth mode- For
POSTandPUT, write the JSON body into a temporary file whenever the payload is non-trivial. - Execute the request via CLI.
- Parse the response JSON.
- If needed, paginate.
- Present the result to the user.
Never do this
- do not only describe the endpoint without calling it
- do not invent Jira data without an HTTP request
- do not inline large JSON payloads into shell commands if quoting is likely to break
- do not expose token values in terminal output
Canonical transport on Linux
Use Bash + curl.
Linux preflight
: "${ATREST_JIRA_BASE_URL:?Missing ATREST_JIRA_BASE_URL}"
: "${ATREST_JIRA_AUTH_MODE:?Missing ATREST_JIRA_AUTH_MODE}"
Linux auth handling
JIRA_BASE="${ATREST_JIRA_BASE_URL}"
JIRA_UA="${ATREST_JIRA_USER_AGENT:-openClaw-jira-atrest/1.0}"
if [ "${ATREST_JIRA_AUTH_MODE}" = "basic" ]; then
: "${ATREST_JIRA_EMAIL:?Missing ATREST_JIRA_EMAIL}"
: "${ATREST_JIRA_API_TOKEN:?Missing ATREST_JIRA_API_TOKEN}"
AUTH_HEADER="Authorization: Basic $(printf '%s' "${ATREST_JIRA_EMAIL}:${ATREST_JIRA_API_TOKEN}" | base64 | tr -d 'n')"
elif [ "${ATREST_JIRA_AUTH_MODE}" = "bearer" ]; then
: "${ATREST_JIRA_BEARER_TOKEN:?Missing ATREST_JIRA_BEARER_TOKEN}"
AUTH_HEADER="Authorization: Bearer ${ATREST_JIRA_BEARER_TOKEN}"
else
echo "Unsupported ATREST_JIRA_AUTH_MODE=${ATREST_JIRA_AUTH_MODE}" >&2
exit 1
fi
Linux generic GET template
curl --silent --show-error --fail
--request GET
--url "${JIRA_BASE}/rest/api/3/issue/PROJ-123?fields=summary,status,assignee,updated"
--header "Accept: application/json"
--header "$AUTH_HEADER"
--header "User-Agent: ${JIRA_UA}"
Linux generic POST/PUT template with temp file
cat > /tmp/jira-body.json <<'JSON'
{
"fields": {
"project": { "key": "PROJ" },
"issuetype": { "name": "Task" },
"summary": "Created from openClaw"
}
}
JSON
curl --silent --show-error --fail
--request POST
--url "${JIRA_BASE}/rest/api/3/issue"
--header "Accept: application/json"
--header "Content-Type: application/json"
--header "$AUTH_HEADER"
--header "User-Agent: ${JIRA_UA}"
--data-binary @/tmp/jira-body.json
Linux parsing guidance
- If
jqis available, use it for formatting and extraction. - Otherwise return raw JSON or parse minimally with the shell.
Example:
curl --silent --show-error --fail ... | jq -r '.key, .fields.summary'
Canonical transport on Windows
Use either PowerShell Invoke-RestMethod or curl.exe.
Important:
- In Windows PowerShell / PowerShell, curl can be an alias.
- To force the native curl client, call curl.exe explicitly.
Windows PowerShell preflight
if (-not $env:ATREST_JIRA_BASE_URL) { throw "Missing ATREST_JIRA_BASE_URL" }
if (-not $env:ATREST_JIRA_AUTH_MODE) { throw "Missing ATREST_JIRA_AUTH_MODE" }
Windows PowerShell auth handling
$JiraBase = $env:ATREST_JIRA_BASE_URL.TrimEnd('/')
$JiraUa = if ($env:ATREST_JIRA_USER_AGENT) { $env:ATREST_JIRA_USER_AGENT } else { 'openClaw-jira-atrest/1.0' }
if ($env:ATREST_JIRA_AUTH_MODE -eq 'basic') {
if (-not $env:ATREST_JIRA_EMAIL) { throw 'Missing ATREST_JIRA_EMAIL' }
if (-not $env:ATREST_JIRA_API_TOKEN) { throw 'Missing ATREST_JIRA_API_TOKEN' }
$pair = "{0}:{1}" -f $env:ATREST_JIRA_EMAIL, $env:ATREST_JIRA_API_TOKEN
$basic = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($pair))
$AuthHeader = "Basic $basic"
}
elseif ($env:ATREST_JIRA_AUTH_MODE -eq 'bearer') {
if (-not $env:ATREST_JIRA_BEARER_TOKEN) { throw 'Missing ATREST_JIRA_BEARER_TOKEN' }
$AuthHeader = "Bearer $($env:ATREST_JIRA_BEARER_TOKEN)"
}
else {
throw "Unsupported ATREST_JIRA_AUTH_MODE=$($env:ATREST_JIRA_AUTH_MODE)"
}
$Headers = @{
Accept = 'application/json'
Authorization = $AuthHeader
'User-Agent' = $JiraUa
}
Windows PowerShell generic GET template
$response = Invoke-RestMethod `
-Method Get `
-Uri "$JiraBase/rest/api/3/issue/PROJ-123?fields=summary,status,assignee,updated" `
-Headers $Headers
$response.key
$response.fields.summary
Windows PowerShell generic POST/PUT template with temp file
$payload = @{
fields = @{
project = @{ key = 'PROJ' }
issuetype = @{ name = 'Task' }
summary = 'Created from openClaw'
}
} | ConvertTo-Json -Depth 20
$tmp = Join-Path $env:TEMP 'jira-body.json'
Set-Content -Path $tmp -Value $payload -Encoding UTF8
$Headers['Content-Type'] = 'application/json'
$response = Invoke-RestMethod `
-Method Post `
-Uri "$JiraBase/rest/api/3/issue" `
-Headers $Headers `
-Body (Get-Content -Path $tmp -Raw)
Windows native curl template
curl.exe --silent --show-error --fail `
--request GET `
--url "$JiraBase/rest/api/3/issue/PROJ-123?fields=summary,status,assignee,updated" `
--header "Accept: application/json" `
--header "Authorization: $AuthHeader" `
--header "User-Agent: $JiraUa"
Reusable helper pattern (recommended for openClaw)
Whenever possible, define one reusable request helper in the active shell session and use it for all Jira calls.
A ready-to-copy reference is provided in:
- refs/cli-rest-quickref.md
This dramatically increases the chance that openClaw actually performs the HTTP call instead of drifting into abstract API discussion.
Request building rules by command type
GET requests
- Build final URL with encoded query parameters.
- Prefer querystring parameters over JSON body.
- Safe for: reads, searches, list operations.
POST requests
- Prefer JSON temp file for non-trivial body.
- Use for: issue create, comment add, transitions apply, sprint create, sprint add issues, worklog add.
PUT requests
- Prefer JSON temp file for non-trivial body.
- Use for: issue edit, assign, comment update, sprint update.
DELETE requests
- Only execute when user intent is explicit.
- Require confirmation unless the user already clearly asked to delete.
Response handling rules
Success
200/201: parse and summarize JSON response204: report success, then optionally follow up with a GET if the user expects the updated resource
Error handling
400: invalid payload, invalid JQL, missing required fields, or bad field ids401: missing or invalid authentication403: authenticated but missing permission or blocked by project/board rules404: resource not found, wrong key/id, or inaccessible resource409: conflict (workflow/state/business rule)429: rate limit; respectRetry-Afterif present, then retry with backoff
Always explain the Jira-specific cause as clearly as possible.
Pagination rules
Platform v3 issue search
For jira.issues.searchJql:
- use nextPageToken until isLast=true
- if the user only asked for a quick answer, stop after a reasonable page size and summarize
StartAt-based endpoints
For endpoints that use startAt and maxResults:
- loop until all required items are collected or the user-requested limit is reached
Command-to-HTTP execution mapping
The following mappings are normative. They are not examples only; they define how openClaw should actually perform the CLI call.
Command Catalog
1) Projects & Users (Platform v3)
jira.projects.search
- GET
/rest/api/3/project/search - Query:
startAt,maxResults, optional filters supported by Jira - Use for: selecting a project id/key, listing available projects
- Output: id, key, name, projectTypeKey/style if available
- CLI rule: perform a GET request against the Platform v3 base path
jira.users.search
- GET
/rest/api/3/user/search - Query:
query(string), optional pagination params supported by Jira - Use for: resolving a person name or email fragment into
accountId - CLI rule: perform a GET request against the Platform v3 base path
2) Issue search & read (Platform v3)
jira.issues.searchJql (Enhanced search)
- GET
/rest/api/3/search/jql(or POST for very long JQL) - Query:
jql,nextPageToken,maxResults,fields[],expand,properties[],fieldsByKeys,failFast,reconcileIssues[] - Pagination: use
nextPageTokenuntilisLast=true - Default: use
ATREST_JIRA_DEFAULT_MAX_RESULTSandATREST_JIRA_DEFAULT_FIELDSif provided - Output: list of issues with key fields
- CLI rule: encode JQL correctly; for Linux prefer
--get --data-urlencodeor a fully encoded URL; for PowerShell prefer a URI string with encoded query parameters
jira.issues.get
- GET
/rest/api/3/issue/{issueIdOrKey} - Query:
fields(comma-separated or array, depending on client),expand - Output: key, summary, status, assignee, description (ADF), priority, labels, updated
- CLI rule: perform a GET request and summarize requested fields only
jira.issues.changelog
- GET
/rest/api/3/issue/{issueIdOrKey}/changelog - Query:
startAt,maxResults - Output: recent changes (field, from, to, author, created)
- CLI rule: paginate if the user asks for full history
3) Create & update issues (Platform v3)
jira.issues.create
- POST
/rest/api/3/issue - Body: see
refs/jira-json-quickref.md#issue-create - Required fields:
project,issuetype,summary - Common optional:
description(ADF),priority,labels,assignee(accountId) - Output: created issue key + self link
- CLI rule: always write non-trivial JSON to a temp file before POSTing
jira.issues.edit
- PUT
/rest/api/3/issue/{issueIdOrKey} - Query:
notifyUsers,returnIssue,overrideScreenSecurity,overrideEditableFlag,expand - Body:
fieldsand/orupdate(operations) - Rule: transitions are NOT done here; use the transitions endpoint instead
- Body reference:
refs/jira-json-quickref.md#issue-edit - Output:
204unlessreturnIssue=true - CLI rule: always use a JSON body file for operation-based updates
jira.issues.assign
- PUT
/rest/api/3/issue/{issueIdOrKey}/assignee - Body:
{ "accountId": "..." }(ornullfor unassigned where allowed) - Use for: assigning to a user by accountId
- Output:
204 - CLI rule: resolve accountId first if needed, then execute the PUT request
jira.issues.transitions.list
- GET
/rest/api/3/issue/{issueIdOrKey}/transitions - Query:
expand, optional filters supported by Jira - Use for: retrieving available workflow transitions and ids
- Output: list transitions: id, name, to.status
- CLI rule: do this first if the user names a status but not a transition id
jira.issues.transitions.apply
- POST
/rest/api/3/issue/{issueIdOrKey}/transitions - Body:
{ "transition": { "id": "X" }, ... }optionally plusupdate.comment.addetc. - Body reference:
refs/jira-json-quickref.md#issue-transition - Output:
204 - CLI rule: if the user said “move to Done”, first list transitions, map the human name to the transition id, then apply the POST request
jira.issues.delete (destructive)
- DELETE
/rest/api/3/issue/{issueIdOrKey} - Query:
deleteSubtasks(optional) - Require explicit user intent before calling
- Output:
204 - CLI rule: never execute unless the user explicitly asked to delete
4) Comments (Platform v3)
jira.comments.list
- GET
/rest/api/3/issue/{issueIdOrKey}/comment - Query:
startAt,maxResults,orderBy,expand - Output: comment id, author, created/updated, body (ADF), visibility
- CLI rule: parse and present comment text in readable form when possible
jira.comments.add
- POST
/rest/api/3/issue/{issueIdOrKey}/comment - Body:
{ "body": <ADF>, "visibility": <optional>, "properties": <optional> } - Body reference:
refs/jira-json-quickref.md#comment-add - Output: created comment (id, timestamps, body)
- CLI rule: if the user provides plain text, convert it to minimal ADF before POSTing
jira.comments.update
- PUT
/rest/api/3/issue/{issueIdOrKey}/comment/{id} - Body: same shape as add (
body/visibility/properties) - Output: updated comment
- CLI rule: use a temp JSON file for the body
jira.comments.delete (destructive)
- DELETE
/rest/api/3/issue/{issueIdOrKey}/comment/{id} - Require explicit user intent before calling
- Output:
204 - CLI rule: same destructive-action safeguards as issue delete
5) Worklogs (Platform v3)
jira.worklogs.list
- GET
/rest/api/3/issue/{issueIdOrKey}/worklog - Output: worklog entries (id, author, started, timeSpentSeconds, comment ADF)
- CLI rule: if the user wants totals, sum
timeSpentSeconds
jira.worklogs.add
- POST
/rest/api/3/issue/{issueIdOrKey}/worklog - Body reference:
refs/jira-json-quickref.md#worklog-add - Output: created worklog
- CLI rule: create ADF comment only when the user supplied text
6) Boards & Sprints (Agile API)
jira.boards.list
- GET
/rest/agile/1.0/board - Query:
startAt,maxResults, filters liketype,name,projectKeyOrId, etc. - Output: board id, name, type
- CLI rule: use Agile API base path, not Platform v3
jira.boards.get
- GET
/rest/agile/1.0/board/{boardId} - Output: board details (location, type)
- CLI rule: use Agile API base path
jira.boards.backlog
- GET
/rest/agile/1.0/board/{boardId}/backlog - Query:
startAt,maxResults,jql,fields,expand - Output: backlog issues
- CLI rule: use Agile API base path and paginate if required
jira.boards.issues
- GET
/rest/agile/1.0/board/{boardId}/issue - Query:
startAt,maxResults,jql,fields,expand - Output: issues currently on the board (by board column mapping)
- CLI rule: use Agile API base path
jira.boards.sprints
- GET
/rest/agile/1.0/board/{boardId}/sprint - Query:
startAt,maxResults,state - Output: sprints (id, name, state, dates)
- CLI rule: use Agile API base path
jira.boards.sprint.issues
- GET
/rest/agile/1.0/board/{boardId}/sprint/{sprintId}/issue - Query:
startAt,maxResults, optional filters - Output: issues in that sprint (board view)
- CLI rule: use Agile API base path
7) Sprint lifecycle (Agile API)
jira.sprints.create
- POST
/rest/agile/1.0/sprint - Body reference:
refs/jira-json-quickref.md#sprint-create - Output: created sprint
- CLI rule: always post JSON via temp file or serialized body string
jira.sprints.get
- GET
/rest/agile/1.0/sprint/{sprintId} - Output: sprint details
- CLI rule: use Agile API base path
jira.sprints.update
- PUT
/rest/agile/1.0/sprint/{sprintId} - Body: full sprint object fields
- Important: missing fields may be nulled depending on request shape and endpoint semantics
- Use for: rename, goal, start, close by state changes when allowed
- CLI rule: read sprint first when there is any risk of overwriting fields unintentionally
jira.sprints.issues
- GET
/rest/agile/1.0/sprint/{sprintId}/issue - Output: sprint issues
- CLI rule: use Agile API base path
jira.sprints.addIssues
- POST
/rest/agile/1.0/sprint/{sprintId}/issue - Body:
{ "issues": ["PROJ-1", "PROJ-2", ...] } - Output:
204on success - CLI rule: send exact issue keys in the JSON body
Practical command examples that openClaw can imitate exactly
These are concrete examples to reduce ambiguity.
Search issues by JQL on Linux
JQL='project = PROJ AND statusCategory != Done ORDER BY updated DESC'
curl --silent --show-error --fail --get
--url "${JIRA_BASE}/rest/api/3/search/jql"
--data-urlencode "jql=${JQL}"
--data-urlencode "maxResults=${ATREST_JIRA_DEFAULT_MAX_RESULTS:-50}"
--data-urlencode "fields=${ATREST_JIRA_DEFAULT_FIELDS:-summary,status,assignee,priority,updated}"
--header "Accept: application/json"
--header "$AUTH_HEADER"
--header "User-Agent: ${JIRA_UA}"
Search issues by JQL on Windows PowerShell
$jql = 'project = PROJ AND statusCategory != Done ORDER BY updated DESC'
$maxResults = if ($env:ATREST_JIRA_DEFAULT_MAX_RESULTS) { $env:ATREST_JIRA_DEFAULT_MAX_RESULTS } else { '50' }
$uri = "$JiraBase/rest/api/3/search/jql?maxResults=$maxResults&fields=summary,status,assignee,priority,updated&jql=$([uri]::EscapeDataString($jql))"
Invoke-RestMethod -Method Get -Uri $uri -Headers $Headers
Add a comment from plain text on Linux
cat > /tmp/comment.json <<'JSON'
{
"body": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "Work completed and verified." }
]
}
]
}
}
JSON
curl --silent --show-error --fail
--request POST
--url "${JIRA_BASE}/rest/api/3/issue/PROJ-123/comment"
--header "Accept: application/json"
--header "Content-Type: application/json"
--header "$AUTH_HEADER"
--header "User-Agent: ${JIRA_UA}"
--data-binary @/tmp/comment.json
Transition an issue on Windows PowerShell
$transitionPayload = @{
transition = @{ id = '31' }
} | ConvertTo-Json -Depth 10
$Headers['Content-Type'] = 'application/json'
Invoke-RestMethod `
-Method Post `
-Uri "$JiraBase/rest/api/3/issue/PROJ-123/transitions" `
-Headers $Headers `
-Body $transitionPayload
Output conventions (recommended)
When replying to the user after an API call:
- For issue lists: show KEY — Summary (Status) [Assignee] updated <date>
- For single issue: show key fields + the user-requested detail (description/comments/etc.)
- For updates/transitions: confirm what changed + resulting status/assignee
- For failures: report the HTTP status and the Jira-relevant reason in plain English
Recommendations that improve openClaw reliability
These are strongly recommended additions to prompts and agent behavior.
1) Force execution language
Add wording like:
- “For every jira.* action, execute a real CLI HTTP request. Do not stop at endpoint explanation.”
- “On Linux use curl; on Windows use curl.exe or Invoke-RestMethod.”
2) Force JSON temp files for write operations
Add wording like: - “For POST/PUT bodies larger than one line, always write JSON to a temp file first.”
This prevents the most common quoting failures.
3) Force an execution transcript shape
Require the agent to think in this order: 1. selected command 2. selected endpoint 3. constructed URL 4. constructed body file if any 5. executed CLI request 6. summarized response
4) Add a minimal Jira connectivity self-test
Before complex Jira work, allow the agent to verify connectivity with a harmless call such as:
- GET /rest/api/3/myself
- or GET /rest/api/3/project/search?maxResults=1
5) Keep one canonical transport per OS
Do not let the agent improvise between many different HTTP clients.
- Linux: curl
- Windows: Invoke-RestMethod or curl.exe
6) Resolve names before mutating data
For assignees, transitions, board ids, and sprint ids, first resolve the exact Jira identifier, then perform the write operation.
Quickref — embedding app data into Jira issue text
For patterns and ready-to-copy ADF payload snippets, including an example for “ContentCraft: Mermaid Diagrams for Jira”, see:
- refs/app-embedding-quickref.md
JSON and CLI references
refs/jira-json-quickref.md(payload shapes, short parameter notes, ADF helper)refs/jql-cheatsheet.md(ready-to-use JQL patterns)refs/openclaw_env_example.json(env snippet)refs/app-embedding-quickref.md(how to embed app data into Jira text bodies; includes ContentCraft Mermaid example)refs/cli-rest-quickref.md(Linux Bash + Windows PowerShell reusable request helpers and concrete REST execution examples)