Use when the user mentions Jira, a ticket key (PROJ-XXX), or asks to perform any Jira read/write/transition/link/comment/search operation, or to structure a freeform request into a Jira task.
Scanned 6/5/2026
Install via CLI
openskills install Lumyk/jira-planner-skill---
name: jira-planner
description: "Use when the user mentions Jira, a ticket key (PROJ-XXX), or asks to perform any Jira read/write/transition/link/comment/search operation, or to structure a freeform request into a Jira task."
---
# Jira Planner
Single entry point for any Jira-Cloud operation.
**Core principle:** Extract max info from user first, research what's missing, never fabricate.
## Conversation language — always detect
Two distinct languages are in play:
- **Conversation language** — the language the user is currently typing in. Detect from the most recent user messages. **All UI text generated by this skill** — `AskUserQuestion` prompts and option labels/descriptions, status updates, error wording, confirmations — MUST be translated to this language at runtime. Default to English only when the user's messages contain no signal of any other natural language (e.g. only English words, English code identifiers, or pure punctuation). The script the user types in is not the criterion — German, Polish, Vietnamese, **romanized/transliterated text from any non-Latin-script language**, or **code-mixed messages** (English vocabulary salted with non-English morphemes/grammar) all signal a non-English conversation. Treat any unambiguous lexical or morphological signal of another language as decisive, regardless of script.
- **`config.bodyLanguage`** — the language of created Jira artifacts (issue body, comments). Used by `body-templates.md`. Independent of conversation language: a Ukrainian-speaking user may keep tickets in English for a mixed team.
The conversation-language rule applies **before** the config gate too — the very first `AskUserQuestion` in `setup.md` must already be in the user's language, even though `config.bodyLanguage` does not exist yet.
Example placeholders in this skill's docs are written in English as the canonical reference; translate them at runtime, do not echo them verbatim.
## Tenant-data hygiene — strict
Never surface concrete tenant values (project keys, custom-field IDs/names, option IDs, ticket keys, repo paths, Atlassian site domains, API URLs, accountIds, label names, automation field names) **anywhere in skill-generated text** — `AskUserQuestion` option labels, option descriptions, **the question prompt itself**, status messages, error wording, or summaries — unless that value was obtained in the current turn from a live MCP/acli tool call, or the user has explicitly typed it in a message during this conversation. In particular:
- **Forbidden sources:** prior-session memory, `MEMORY.md`, project `CLAUDE.md` / `GEMINI.md` / any system-injected context block, the model's training data, "I remember the user uses X".
- **"Typed by the user"** means the user actively wrote the value into a chat message in this conversation. System-injected context (auto-attached files, CLAUDE.md, environment dumps) does NOT count.
- Use open-ended questions when the value is tenant-specific. Generic placeholders are fine ONLY if obviously fictional: `<PROJECT_KEY>`, `<EPIC-KEY>`, `<org>/<repo>`, `<your-domain>`. Avoid real-looking names (`acme-corp`, `example.com`) — they prime pattern-matching toward tenant data.
- This rule applies during setup AND during every other skill operation. Violating it leaks tenant info to the user (and to the conversation transcript) even when public skill files are clean.
See `setup.md` "Tenant-data hygiene" for the same rule with examples.
## Configuration gate — read FIRST
The skill is configured per-tenant via `config.local.yaml` in this skill directory.
1. Read `~/.claude/skills/jira-planner/config.local.yaml`.
2. **If the file is missing** → load `setup.md` and follow it. Do NOT attempt any Jira op until config exists.
3. **If the user pasted a config YAML in the conversation** → treat that as a one-shot config import. Follow `setup.md` Path A — it has the full validation rules (required top-level keys: `site`, `cloudId`, `projects`, `bodyLanguage`; per-project required keys: `issueTypes`, `customFields`). Do NOT write an unvalidated config.
4. **If the user has a well-specified single ticket and config is missing** → setup.md "Minimal bootstrap" path is available: discover only `cloudId`, the target project's `issueTypes`, and the custom fields needed for the requested ticket; defer the rest. The user picks this via the first AskUserQuestion in setup.
5. Treat the loaded config as the **only** source of truth for: cloud ID, project keys, issue type IDs, custom field IDs, option IDs, automation behaviors, research repos, API docs, body language, default reporter.
6. The skill may **update** `config.local.yaml` during a session — see "Self-updating config" below.
**Never substitute MEMORY.md, CLAUDE.md, prior-session context, or assumptions from the user's message for `config.local.yaml`.** If you "remember" a customfield ID from a prior session, you must still verify it against the config; if config is missing, run setup.
**Required reads after config gate:**
- `transport.md` — MCP/acli matrix, ADF, link semantics, post-create verify.
- `process.md` — 12-step new-task flow (load only on new-task intent).
- `body-templates.md` — body skeletons (load only on new-task intent).
- `user-notes.md` — `user.notes[]` matching mechanics (load only on new-task intent).
**Required sub-skills (new-task flow only):** `superpowers:dispatching-parallel-agents`, `superpowers:using-git-worktrees`.
## Transport — MCP-default, acli-opportunistic
Default for every op: **MCP** (`mcp__claude_ai_Atlassian__*` if connected, else `mcp__jira__*`). One-shot creates with custom fields, transitions, links — all MCP.
Optimization: `acli` for read ops + simple writes when allowlisted. Run `acli jira auth status` once per Jira flow; if exit 0 + `✓ Authenticated`, cache `ACLI_AVAILABLE=true`. Verify auth points to the same site as `config.site`.
Decision rules + acli gotchas: `transport.md`.
## Scope Router
| User intent | What to do |
|---|---|
| **New task** — freeform problem/bug/feature → ticket. | Read `process.md` → follow 12-step flow (step 0 = transport detection + config load, step 12 = mandatory post-create verify). |
| **Comment** — add/edit on existing ticket. | `transport.md` → "Tool Preference Matrix" + "Comment Formatting". MCP `addCommentToJiraIssue` with `contentFormat: "markdown"` is the fast path. acli `comment create --body` does NOT parse Markdown — use `--body-adf body.json` for formatting on acli. |
| **Transition** — change status. | `transport.md` row "Transition status". If you don't know the exact status name, list via MCP `getTransitionsForJiraIssue` (acli cannot list). |
| **Link** — create issue link. | `transport.md` → "Issue Links". MCP `inwardIssue` = actor, `outwardIssue` = recipient; acli `--out` = actor, `--in` = recipient. |
| **View / search** — read ticket, list comments/watchers/links, JQL. | `transport.md` → "Tool Preference Matrix". acli if available (faster, no approval prompts); otherwise MCP `getJiraIssue` / `searchJiraIssuesUsingJql`. |
| **Field update** (priority, assignee, parent, etc.) | `transport.md`. MCP `editJiraIssue` is the one-shot path. |
| **Setup / refresh config** | Read `setup.md`. |
**Red flag:** if you think *"this is just a direct Jira op, no skill needed"* — STOP. That's the rationalization that produces unrendered markdown comments, reversed link directions, doubled summary prefixes, and silently-dropped custom fields. Read `transport.md` AND `config.local.yaml`.
## When NOT to use
- Ticket key mentioned only as a git ref (rebase, diff, build) — the actual ask is non-Jira.
- Project key is **not** listed in `config.projects` — ask the user to add it via `/jira-planner setup` first.
## User preferences and memory (`config.user.*`)
`config.user` is **user-owned**: skill reads on session start, applies where relevant, **never overwrites** without explicit confirmation. On session start: parse `config.user.defaults` and `config.user.notes`, hold in working context.
- `user.defaults.priority` / `user.defaults.assignee` — fallbacks when user did not specify. `null` → standard heuristic (priority) or skip (assignee).
- `user.notes[]` — free-text persistent instructions, scanned at process steps 2 + 6.
Detailed mechanics (note matching, ambiguity handling, conflict precedence, write-back rules) → `user-notes.md`. Load on new-task intent.
## Self-updating config
When the skill learns something new during a session, propose writing it back to `config.local.yaml`. Always show the diff and get explicit `apply` confirmation. Never silently mutate config. Triggers:
- New option ID returned by `getJiraIssueTypeMetaWithFields` → add under `projects.<KEY>.customFields.<NAME>.options.<VALUE>`, bump `cache.lastVerified`.
- Create call fails with `Field 'X' cannot be set` → record under `projects.<KEY>.epicGotchas` or the relevant custom field; pick fallback from `transport.md`.
- User mentions a new automation rule → add to `projects.<KEY>.automation`.
## Auto mode discipline
Auto mode = no wait between steps. NOT = skip steps.
All `process.md` steps run regardless of mode. Steps 7 (present draft), 9 (security scan), 10 (self-review) are gates, not courtesies.
If a step reveals issue (secret leak, wrong field, missing required) → STOP. Auto mode does not authorise pushing flawed work.
## Common Mistakes
| Mistake | Fix |
|---------|-----|
| Defaulting to acli for every op | MCP-default. Use acli only where `transport.md` Tool Preference Matrix marks it `✓ if available`. |
| Skipping post-create verification | Mandatory `getJiraIssue` (or `acli view --fields "*all"`) after every create — Jira silently drops custom fields not on the create screen. |
| Forgetting a custom field marked `required: true` in config | All custom fields with `required: true` MUST be in the create payload. Create fails otherwise. |
| Hardcoding option value strings | Use option IDs from `config.projects.<KEY>.customFields.<NAME>.options` — IDs are stable across renames. |
| Doubled summary prefix (e.g. `[X] [X] foo`) | If `projects.<KEY>.automation.summaryPrefixFromField` is set, submit summary WITHOUT the prefix. Automation adds it once. |
| Setting labels manually when automation populates them | If `projects.<KEY>.automation.autoLabelsFromFields` is non-empty, do NOT set `labels` in the create payload. |
| Submitting multiple values to a field listed in `multiValueSplitsIssue` | Automation will split the issue into N tickets. Submit one value unless the split is intentional. |
| Guessing link direction | MCP: `inwardIssue` = actor, `outwardIssue` = recipient. acli: `--out` = actor, `--in` = recipient. See `transport.md` "Issue Links". |
| `acli view --key KEY` | `acli view` is **positional**: `view KEY`. Every other workitem subcommand uses `--key`. |
| `acli search` parsed as `{issues:[…]}` | acli `search --json` returns a top-level array. Parse `d[0]`. |
| Fabricating new-task details | Facts only. "Unknown" (translated to `config.bodyLanguage`) is valid. |
| Templates from memory | Always read `process.md` + `body-templates.md` + `config.local.yaml`. |
| Reading hardcoded field IDs from skill files | All field IDs live in `config.local.yaml`. Skill files never name a specific `customfield_*`. |
No comments yet. Be the first to comment!