jira-transitions
Move Jira issues through workflow states. Use when transitioning issues (To Do, In Progress, Done) or setting resolutions.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Move Jira issues through workflow states. Use when transitioning issues (To Do, In Progress, Done) or setting resolutions.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Manage Jira Agile boards and sprints. Use when listing boards, creating sprints, or moving issues to/from sprints.
Authenticate with Jira Cloud REST API using API tokens. Use when setting up Jira connections, validating credentials, or handling rate limiting.
Create, read, update, and delete Jira issues. Use when managing Stories, Tasks, Bugs, or Epics - includes field updates and metadata.
Administer Jira projects. Use when creating/archiving projects, managing components, versions, roles, permissions, or project configuration.
Manage Jira projects. Use when listing projects, getting project configuration, retrieving issue types, or managing components and versions.
Orchestrate Jira workflows end-to-end. Use when building stories with approvals, transitioning items through lifecycle states, or syncing task completion with Jira.
| name | jira-transitions |
| description | Move Jira issues through workflow states. Use when transitioning issues (To Do, In Progress, Done) or setting resolutions. |
Move issues through workflow states. Get available transitions and execute status changes.
Transition IDs are NOT standardized - they vary by:
Always query available transitions first before attempting to transition.
interface Transition {
id: string;
name: string;
to: {
id: string;
name: string;
statusCategory: {
id: number;
key: string;
name: string;
};
};
fields?: Record<string, {
required: boolean;
name: string;
allowedValues?: Array<{ id: string; name: string }>;
}>;
}
interface TransitionsResponse {
transitions: Transition[];
}
async function getTransitions(
client: JiraClient,
issueKeyOrId: string
): Promise<Transition[]> {
const response = await client.request<TransitionsResponse>(
`/issue/${issueKeyOrId}/transitions?expand=transitions.fields`
);
return response.transitions;
}
async function findTransitionByName(
client: JiraClient,
issueKeyOrId: string,
targetStatusName: string
): Promise<Transition | null> {
const transitions = await getTransitions(client, issueKeyOrId);
return transitions.find(
t => t.name.toLowerCase() === targetStatusName.toLowerCase() ||
t.to.name.toLowerCase() === targetStatusName.toLowerCase()
) || null;
}
interface TransitionOptions {
resolution?: { name: string } | { id: string };
comment?: string;
fields?: Record<string, any>;
}
async function transitionIssue(
client: JiraClient,
issueKeyOrId: string,
transitionId: string,
options: TransitionOptions = {}
): Promise<void> {
const body: any = {
transition: { id: transitionId },
};
if (options.resolution || options.fields) {
body.fields = { ...options.fields };
if (options.resolution) {
body.fields.resolution = options.resolution;
}
}
if (options.comment) {
body.update = {
comment: [
{
add: {
body: {
type: 'doc',
version: 1,
content: [
{
type: 'paragraph',
content: [{ type: 'text', text: options.comment }],
},
],
},
},
},
],
};
}
await client.request(`/issue/${issueKeyOrId}/transitions`, {
method: 'POST',
body: JSON.stringify(body),
});
}
async function moveIssueTo(
client: JiraClient,
issueKeyOrId: string,
targetStatus: string,
options: TransitionOptions = {}
): Promise<boolean> {
const transition = await findTransitionByName(client, issueKeyOrId, targetStatus);
if (!transition) {
console.error(`No transition found to status: ${targetStatus}`);
return false;
}
// Check if resolution is required
if (transition.fields?.resolution?.required && !options.resolution) {
// Default to "Done" resolution
options.resolution = { name: 'Done' };
}
await transitionIssue(client, issueKeyOrId, transition.id, options);
return true;
}
async function bulkTransition(
client: JiraClient,
issueKeys: string[],
targetStatus: string,
options: TransitionOptions = {}
): Promise<{ success: string[]; failed: string[] }> {
const results = { success: [] as string[], failed: [] as string[] };
for (const issueKey of issueKeys) {
try {
const success = await moveIssueTo(client, issueKey, targetStatus, options);
if (success) {
results.success.push(issueKey);
} else {
results.failed.push(issueKey);
}
} catch (error) {
results.failed.push(issueKey);
}
}
return results;
}
Most Jira projects have these standard transitions:
| From Status | Transition Name | To Status |
|---|---|---|
| To Do | Start Progress | In Progress |
| In Progress | Done | Done |
| In Progress | Stop Progress | To Do |
| Done | Reopen | To Do |
Note: These names vary by workflow configuration.
When transitioning to "Done", you often need a resolution:
| Resolution | Description |
|---|---|
| Done | Work completed |
| Won't Do | Not planning to do |
| Duplicate | Already exists |
| Cannot Reproduce | Cannot reproduce issue |
curl -X GET "$JIRA_BASE_URL/rest/api/3/issue/SCRUM-123/transitions?expand=transitions.fields" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)" \
-H "Accept: application/json"
curl -X POST "$JIRA_BASE_URL/rest/api/3/issue/SCRUM-123/transitions" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)" \
-H "Content-Type: application/json" \
-d '{
"transition": { "id": "21" }
}'
curl -X POST "$JIRA_BASE_URL/rest/api/3/issue/SCRUM-123/transitions" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)" \
-H "Content-Type: application/json" \
-d '{
"transition": { "id": "31" },
"fields": {
"resolution": { "name": "Done" }
}
}'
curl -X POST "$JIRA_BASE_URL/rest/api/3/issue/SCRUM-123/transitions" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)" \
-H "Content-Type: application/json" \
-d '{
"transition": { "id": "21" },
"update": {
"comment": [
{
"add": {
"body": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [{ "type": "text", "text": "Moving to In Progress" }]
}
]
}
}
}
]
}
}'
A successful transition returns 204 No Content with an empty body.
| Error | Cause | Solution |
|---|---|---|
| 400 Bad Request | Invalid transition ID | Query transitions first |
| 400 Bad Request | Missing required resolution | Add resolution field |
| 403 Forbidden | No permission to transition | Check workflow permissions |
| 404 Not Found | Issue doesn't exist | Verify issue key |
{
"errorMessages": [
"You must specify a resolution when transitioning issues to the 'Done' status."
],
"errors": {
"resolution": "Resolution is required."
}
}
async function discoverWorkflow(
client: JiraClient,
issueKeyOrId: string
): Promise<Map<string, Transition[]>> {
// Get transitions from current state
const transitions = await getTransitions(client, issueKeyOrId);
console.log(`Available transitions from current state:`);
for (const t of transitions) {
console.log(` ${t.id}: ${t.name} → ${t.to.name}`);
if (t.fields?.resolution?.required) {
console.log(` (requires resolution)`);
}
}
return new Map([
['current', transitions]
]);
}