LI

lisa-atlassian-access

Centralized chokepoint for all JIRA and Confluence operations, ensuring secure, consistent API interaction.

Install

mkdir -p .claude/skills/lisa-atlassian-access-codyswanngt && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/18863" && unzip -o skill.zip -d .claude/skills/lisa-atlassian-access-codyswanngt && rm skill.zip

Installs to .claude/skills/lisa-atlassian-access-codyswanngt

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Vendor-neutral access layer for Atlassian (JIRA + Confluence). Every jira-* and confluence-* skill MUST delegate through this skill rather than calling Atlassian directly. Resolves a substrate per operation, binding JIRA writes to the configured cloudId via Atlassian REST whenever token auth is available and using acli only for reads or as a guarded fallback. For non-write acli operations, acli is used when installed and switchable to a profile matching the configured site; mismatched active profiles are skipped only after switch plus re-verification fails.
563 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Intermediate

Key capabilities

  • Route Atlassian operations to a substrate
  • Enforce connection match for operations
  • Return structured operation results
  • Handle JIRA write operations via Atlassian REST
  • Use acli for non-write operations or as a fallback
  • Manage token authentication for Atlassian access

How it works

The skill routes each Atlassian operation to an appropriate substrate, such as `acli` or Atlassian REST, after verifying the connection identity. It returns a structured result or an error.

Inputs & outputs

You give it
operation: read-ticket key: PROJ-123
You get back
structured operation result (JSON object)

When to use lisa-atlassian-access

  • Routing a JIRA ticket update
  • Accessing Confluence documentation
  • Verifying Atlassian connection settings
  • Transitioning ticket status

About this skill

Atlassian Access: $ARGUMENTS

Single chokepoint for all Atlassian operations. Routes each op to a substrate, enforces connection match, returns structured result. Caller skills (jira-*, confluence-*) MUST go through this — they MUST NOT invoke acli directly, call Atlassian MCP tools directly, or curl the Atlassian REST API themselves.

Invocation contract

The caller passes one operation plus its arguments. Operations are listed in the dispatch table below. The skill returns either the structured operation result (JSON when the substrate provides it) or a clear error.

operation: read-ticket  key: PROJ-123
operation: write-ticket payload: {...}
operation: transition   key: PROJ-123  to: "In Review"
operation: comment      key: PROJ-123  body: "..."
operation: search-issues jql: "project = SE AND status = Open"
operation: read-page    id: 12345
operation: write-page   payload: {...}

Workflow

Step 1 — Substrate selection (per operation)

Read config:

SITE=$(jq -r '.atlassian.site // empty' .lisa.config.json)
CLOUDID=$(jq -r '.atlassian.cloudId // empty' .lisa.config.json)
EMAIL=$(jq -r '.atlassian.email // empty' .lisa.config.local.json 2>/dev/null)
[ -z "$CLOUDID" ] && { echo "Error: atlassian.cloudId not set. Run /lisa:setup:atlassian." >&2; exit 1; }

Probe each tier in order; the first that's ready AND identity-matches is the substrate for this operation. Identity-match is verified before any operation; substrates authenticated as a different Atlassian account are switched to the configured profile when one exists, then skipped only if the switch fails or re-verification still mismatches.

substrate=""

# Tier 1: acli for reads and non-write operations only.
#
# Do not choose acli for JIRA writes when curl/token auth is available. acli stores
# one machine-global active account and workitem writes cannot pin a cloudId per
# invocation, so switch-then-write is a TOCTOU risk in multi-account or concurrent
# sessions. Write operations prefer the cloudId-scoped REST URL below.
if [ "$OP_KIND" != "jira-write" ] && command -v acli >/dev/null 2>&1 && acli auth status >/dev/null 2>&1; then
  current_site=$(acli auth status 2>/dev/null | awk '/^  Site:/{print $2}')
  if [ "$current_site" != "$SITE" ]; then
    # acli installed but pointing at a different site. Try switching profiles.
    acli auth switch --site "$SITE" ${EMAIL:+--email "$EMAIL"} >/dev/null 2>&1 || true
    current_site=$(acli auth status 2>/dev/null | awk '/^  Site:/{print $2}')
  fi
  if [ "$current_site" = "$SITE" ]; then
    substrate="acli"
  fi
fi

# Tier 2: Atlassian MCP (if acli not ready OR the operation isn't acli-covered)
# $OP_REQUIRES is a conceptual variable set by the dispatch table to "non-acli" for
# operations that have no acli adapter (e.g. read-page-descendants). It is not a real
# shell variable initialized here — the condition is illustrative pseudo-code.
if [ -z "$substrate" ] || [ "$OP_REQUIRES" = "non-acli" ]; then
  # Probe via mcp__plugin_atlassian_atlassian__getAccessibleAtlassianResources.
  # (Pseudo-code; actual call is the MCP tool invocation, not a bash command.)
  # If the MCP returns a list and $CLOUDID is in it, MCP is identity-matched.
  # If the MCP is unauthenticated or $CLOUDID is NOT in the list, MCP is skipped.
  if mcp_atlassian_authenticated_and_matches_cloudid "$CLOUDID"; then
    : ${substrate:=mcp}
    # Mark MCP as available even if acli already won tier 1 — used for ops acli can't do.
    mcp_available=true
  fi
fi

# Tier 3: curl + API token (headless / multi-account / scoped-token path)
read_atlassian_token() {
  local email="$1"
  [ -n "$ATLASSIAN_API_TOKEN" ] && { echo "$ATLASSIAN_API_TOKEN"; return; }
  local slug=$(echo "$email" | tr '[:upper:]@.' '[:lower:]__')
  local varname="ATLASSIAN_API_TOKEN_${slug}"
  [ -n "${!varname}" ] && { echo "${!varname}"; return; }
  case "$(uname -s)" in
    Darwin)  security find-generic-password -s lisa-atlassian -a "$email" -w 2>/dev/null ;;
    Linux)   command -v secret-tool >/dev/null && secret-tool lookup service lisa-atlassian account "$email" 2>/dev/null ;;
    MINGW*|MSYS*|CYGWIN*)
      # `cmdkey /generic ... /pass:` stores the secret in Windows Credential Manager, but
      # `cmdkey /list` never prints stored passwords (by design). Read the CredentialBlob
      # back via the Win32 CredRead API through PowerShell; pass the target name via an env
      # var to dodge nested quoting, and strip the CRLF powershell.exe appends.
      LISA_CRED_TARGET="lisa-atlassian-${email}" powershell.exe -NoProfile -NonInteractive -Command '
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public static class LisaCred {
  [StructLayout(LayoutKind.Sequential)]
  private struct CREDENTIAL {
    public int Flags; public int Type; public IntPtr TargetName; public IntPtr Comment;
    public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
    public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist;
    public int AttributeCount; public IntPtr Attributes; public IntPtr TargetAlias; public IntPtr UserName;
  }
  [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
  private static extern bool CredRead(string target, int type, int flags, out IntPtr credential);
  [DllImport("advapi32.dll")] private static extern void CredFree(IntPtr cred);
  public static string Read(string target) {
    IntPtr p;
    if (!CredRead(target, 1, 0, out p)) { return null; }
    try {
      CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(p, typeof(CREDENTIAL));
      if (c.CredentialBlobSize == 0) { return String.Empty; }
      return Marshal.PtrToStringUni(c.CredentialBlob, c.CredentialBlobSize / 2);
    } finally { CredFree(p); }
  }
}
"@
[LisaCred]::Read($env:LISA_CRED_TARGET)' 2>/dev/null | tr -d '\r' ;;
  esac
}
TOKEN=$(read_atlassian_token "$EMAIL")
[ -n "$TOKEN" ] && curl_available=true && {
  if [ "$OP_KIND" = "jira-write" ]; then
    substrate="curl"
  else
    : ${substrate:=curl}
  fi
}

# Fail loudly with actionable remediation if nothing works.
if [ -z "$substrate" ]; then
  # Detect plugin enablement state for the suggestion.
  plugin_enabled_global=$(jq -r '.enabledPlugins["atlassian@claude-plugins-official"] // false' ~/.claude/settings.json 2>/dev/null || echo "false")
  plugin_enabled_project=$(jq -r '.enabledPlugins["atlassian@claude-plugins-official"] // false' .claude/settings.json 2>/dev/null || echo "false")
  plugin_enabled_local=$(jq -r '.enabledPlugins["atlassian@claude-plugins-official"] // false' .claude/settings.local.json 2>/dev/null || echo "false")

  cat >&2 <<EOF
Error: no Atlassian access substrate available for site $SITE.

Attempted:
  acli   — $(command -v acli >/dev/null && echo "installed but identity mismatch or unauthenticated" || echo "not installed")
  MCP    — $([ "$plugin_enabled_global" = "true" ] || [ "$plugin_enabled_project" = "true" ] || [ "$plugin_enabled_local" = "true" ] && echo "plugin enabled but not authenticated or cloudId $CLOUDID not in accessible resources" || echo "plugin not enabled in any settings.json scope")
  curl   — no ATLASSIAN_API_TOKEN found for $EMAIL (env, slug-suffixed env, or keychain)

Remediation paths (pick one):

1. Install the Atlassian MCP plugin (local scope — per-developer, gitignored).
   This is the simplest path for single-account developers.

   Run in your terminal:

     jq '.enabledPlugins["atlassian@claude-plugins-official"] = true' \\
       .claude/settings.local.json 2>/dev/null > /tmp/s && \\
       mv /tmp/s .claude/settings.local.json || \\
       echo '{"enabledPlugins":{"atlassian@claude-plugins-official":true}}' > .claude/settings.local.json

   Then restart Claude Code (or run /restart-mcp) to load the plugin, and
   invoke 'mcp__plugin_atlassian_atlassian__authenticate' to complete OAuth.

2. Install acli and authenticate (best for multi-account developers).

     brew tap atlassian/homebrew-acli && brew install acli
     acli auth login   # OAuth as the account matching $EMAIL

3. Provision an API token (headless / CI / scoped-token environments).

     Run /lisa:setup:atlassian — guided flow with clipboard-piped keychain store.

EOF
  exit 1
fi

Operation dispatch then uses $substrate for the primary route. If the operation has no acli adapter and $substrate=acli, fall through to $mcp_available then $curl_available for the actual call. The fall-through stops at the first available tier that can perform the operation.

Step 2 — Connection-match check

The active connection MUST point at the cloudId/site declared in .lisa.config.json. Step 1's substrate selection already tries to switch mismatched acli profiles and verifies the result before selection. This step repeats the assertion before any operation runs — defensive in case the substrate state changed since selection.

Read configured site:

cloudid=$(jq -r '.atlassian.cloudId // empty' .lisa.config.json)
site=$(jq -r '.atlassian.site // empty' .lisa.config.json)   # optional human-readable site URL
email=$(jq -r '.atlassian.email // empty' .lisa.config.json) # optional, for multi-account disambiguation

if [ -z "$cloudid" ]; then
  echo "Error: atlassian.cloudId not set in .lisa.config.json. Run /lisa:setup:atlassian." >&2
  exit 1
fi

CLI mode check:

# Compare active acli profile against config.
current=$(acli auth status --json 2>/dev/null)
current_site=$(echo "$current" | jq -r '.site // empty')
current_email=$(echo "$current" | jq -r '.email // empty')

if [ -n "$site" ] && [ "$current_site" != "$site" ]; then
  # Profile mismatch — switch, then re-verify. Do not trust the switch exit
  # status alone because acli's active account is machine-global state.
  acli auth switch --site "$site" ${email:+--email "$email"}
  current=$(acli auth status --json 2>/dev/null)
  current_site=$(echo "$current" | jq -r '.site // empty')
  current_email=$(echo "$current

---

*Content truncated.*

When not to use it

  • When directly invoking `acli` or `curl` for Atlassian APIs
  • When bypassing connection match for operations
  • When needing to switch substrates mid-operation

Limitations

  • Caller skills must delegate through this skill for Atlassian operations
  • Substrate is decided once per skill invocation
  • Profile mutations are only allowed when acli is the active substrate

How it compares

This skill centralizes Atlassian API interactions, preventing direct calls and ensuring consistent connection management and token authentication, unlike manual API calls.

Compared to similar skills

lisa-atlassian-access side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
lisa-atlassian-access (this skill)021dReviewIntermediate
zendesk153moReviewIntermediate
zapier-workflows118moReviewBeginner
controlling-spotify73moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

More by CodySwannGT

View all by CodySwannGT

lisa-setup-atlassian

CodySwannGT

Set up Atlassian (cloudId + acli profile) for this project. Writes the `atlassian` section of `.lisa.config.json` and enables the Atlassian MCP and/or installs acli as needed. Prerequisite for /lisa:setup:jira and /lisa:setup:confluence.

00

lisa-lint

CodySwannGT

Health-check the LLM Wiki: orphan pages, contradictions, stale claims, broken internal links, missing index/log coverage, structure violations, and secret/tenant leaks. Read-only — reports findings, does not fix them.

00

lisa-parity-code-review

CodySwannGT

Lisa-native code review of the current git diff. Walks every changed hunk and reports correctness bugs, security issues, and obvious defects as severity-ranked findings with file:line references. Vendor-neutral — the cross-agent equivalent of the upstream code-review command, runnable on Codex, agy,

00

lisa-prd-backlink

CodySwannGT

Update a source PRD with an always-written, machine-readable `## Tickets` (alias `## Generated Work`) section linking back to every work item created from it. Each entry carries a parseable ref + URL + type + parent token so the generated child set is readable without scraping prose. Vendor-aware on

00

lisa-acceptance-criteria

CodySwannGT

Acceptance criteria definition. Gherkin user flows (Given/When/Then), error states, UX concerns, and empirical verification from the user perspective.

00

lisa-epic-triage

CodySwannGT

9-step epic triage and 5-step implementation workflow. Ensures epics are fully scoped, broken down, and ordered before execution begins.

00

You might also like

Search skills

Search the agent skills registry