Clone a Jira epic from another project into the PF Jira space with back-links and feature attachment. Use when duplicating COST or cross-project epics into PF for tracking.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add rh-uxd/ai-helpers --skill pf-duplicate-epic --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Pf Duplicate Epic?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/rh-uxd-pf-duplicate-epic)More formats (shields.io, HTML) on the badges page.
---
name: pf-duplicate-epic
description: Clone a Jira epic from another project into the PF Jira space with back-links and feature attachment. Use when duplicating COST or cross-project epics into PF for tracking.
disable-model-invocation: true
---
# Duplicate Epic
Clones a Jira epic (e.g., from the `COST` project) into the PatternFly (`PF`) Jira space, ensures it carries an "is duplicated by" link referencing the original, and sets it as a child of the given feature.
## Requirements
| Tool | Purpose | Install |
|---|---|---|
| `curl` | Jira REST API calls | pre-installed on macOS; `brew install curl` |
| `jq` | JSON parsing and payload construction | `brew install jq` |
The script checks for both tools at startup and exits with a helpful message if either is missing.
## Input Parsing
The command takes exactly two positional arguments:
| Position | Name | Description |
|---|---|---|
| `$1` | `issue` | Any Jira issue key or full URL — Epic, Story, Bug, etc. |
| `$2` | `feature` | The PF feature key or full URL to assign the new epic to |
Both bare keys and full URLs are accepted:
| Input | Parsed key |
|---|---|
| `COST-7355` | `COST-7355` |
| `https://redhat.atlassian.net/browse/COST-7355` | `COST-7355` |
| `PF-3868` | `PF-3868` |
| `https://redhat.atlassian.net/browse/PF-3868` | `PF-3868` |
Pass `$1` and `$2` directly to the script — no further parsing required.
## Prerequisites
The script requires two environment variables:
| Variable | Description |
|---|---|
| `JIRA_USER_EMAIL` | Atlassian account email |
| `JIRA_API_TOKEN` | API token from [id.atlassian.com/manage/api-tokens](https://id.atlassian.com/manage/api-tokens) |
If either is missing, ask the user for their email and direct them to create an API token, then set the variables inline when running the script.
## Workflow
Run the script from the skill directory:
```bash
cd $CLAUDE_SKILL_DIR
bash scripts/duplicate_epic.sh <issue> <feature>
```
The first argument (`issue`) may be an Epic, Story, Bug, or any other issue type. If it is not an Epic, the script automatically resolves its parent epic before cloning.
**Examples:**
```bash
bash scripts/duplicate_epic.sh COST-7355 PF-3868
bash scripts/duplicate_epic.sh COST-7309 PF-3868 # story/bug — script walks up to parent epic automatically
```
With inline credentials:
```bash
JIRA_USER_EMAIL="you@example.com" JIRA_API_TOKEN="your-token" \
bash scripts/duplicate_epic.sh COST-7170 PF-3406
```
## What the Script Does
1. **Resolve current user** — looks up the account ID for the authenticated user (used for the assignee field).
2. **Resolve to an epic** — fetches the given issue. If it is not an `Epic` (e.g., it is a Story or Bug), the script walks up to its parent epic using `fields.parent` (next-gen projects) or `fields.customfield_10014` (classic epic link). Exits with an error if no parent epic can be found.
3. **Find existing clone** — checks the resolved epic's `Duplicate` issue links for any `PF-` issue; skips creation if found.
4. **Clone** — if no clone exists, creates a new Epic in the `PF` project copying the summary and labels. The description is sanitized before cloning: `mediaSingle` and `media` nodes (embedded attachments) are stripped, so embedded images and file attachments will not appear in the PF copy.
5. **Ensure "is duplicated by" link** — adds a `Duplicate` link so the new epic displays "is duplicated by {ORIGINAL EPIC}" in its linked work items; skips if already present.
6. **Set parent and assignee** — assigns the new epic as a child of the given feature and assigns it to the current user (resolved automatically via the API token).
7. **Display results** — prints clickable URLs for the feature, new epic, and original epic.
## Output
After a successful run, display these URLs to the user:
```
Feature: https://redhat.atlassian.net/browse/PF-3406
New Epic: https://redhat.atlassian.net/browse/PF-XXXX
Original Epic: https://redhat.atlassian.net/browse/COST-7170
Input Issue: https://redhat.atlassian.net/browse/COST-7309 ← only shown when input was not itself an epic
```
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!