---
name: multi-agent-setup
language: en
description: "First-run setup wizard: keychain token discovery, Git Identity onboarding, and pipeline preparation. Use when the pipeline is being set up for the first time, or tokens and git identity need onboarding."
user-invocable: true
---

## Setup (Keychain Token + Git Identity Onboarding)

Self-contained setup  -  works with inline `security` commands, no external script **required**. If `$HOME/.claude/scripts/keychain-save.sh` exists, it can be used as an interactive alternative but is not mandatory. The `setup` command starts interactive onboarding.

### Step 0  -  Language Selection

Ask BEFORE anything else. The pipeline has two language fields:

| Field | Controls | Configurable? |
|---|---|---|
| `promptLanguage` | The picker's structural UI chrome only: `AskUserQuestion` `label` + `header`, host error UI, internal contract identifiers | **No  -  fixed to `en`.** Button and chip text stays English. |
| `outputLanguage` | The assistant's non-interactive explanations, status updates, error messages, and pipeline-generated reports | Yes  -  set here, change later via `/multi-agent-language <en\|tr>` |

`promptLanguage` is seeded as `"en"` and never offered to the user. External payloads (commits, PR/Jira/wiki, reviewer/triage prompts, agent-log.md) always stay English regardless.

**Step 0  -  outputLanguage** (English UI per skill-prompt rules):

```
Which language should the assistant use for ITS OWN explanations,
status updates, and pipeline-generated reports?
  1) English
  2) Türkçe
Select (1-2):
```

**Rules:**

- Already set in prefs → skip silently. Change later via `/multi-agent-language <en|tr>` or `/multi-agent-language output <en|tr>`.
- New value → validate against `["en", "tr"]`, atomic write to `prefs.global.outputLanguage`, force `prefs.global.promptLanguage = "en"`, echo confirmation in the chosen `outputLanguage`.
- Unknown input → re-ask once, then abort with a hint pointing to `/multi-agent-language`.

### Step 1  -  Dynamic Keychain Discovery

Instead of checking only hardcoded key names, discover ALL user keys and intelligently map them to services.

**1a. Discover all keys:**
```bash
DISCOVERED=$(security dump-keychain 2>/dev/null | grep '"svce"' | awk -F'"' '{print $4}' | grep -i "^${USER}" | sort -u)
echo "$DISCOVERED"
```

**1b. Standard key names (convention):**

These are the RECOMMENDED key names. When creating NEW keys, use these. But existing keys under different names are perfectly valid  -  the discovery step will find them.

| Service ID | Standard Key Name | Search Keywords |
|------------|------------------|-----------------|
| `jira` | `${USER}_Jira_Access_Token` | `jira` |
| `bitbucket_token` | `${USER}_Bitbucket_Access_Token` | `bitbucket` + (`token` or `access` or `pass`) |
| `bitbucket_user` | `${USER}_Bitbucket_Username` | `bitbucket` + (`user` or `name`) |
| `github` | `${USER}_Github_Access_Token` | `github` or `gh` (exclude `ssh`) |
| `confluence` | `${USER}_Confluence_Access_Token` | `confluence` |
| `figma` | `${USER}_Figma_Access_Token` | `figma` + NOT `mcp` |
| `figma_mcp` | `${USER}_Figma_Mcp_Access_Token` | `figma` + `mcp` |
| `fortify` | `${USER}_Fortify_Access_Token` | `fortify` |
| `firebase` | `${USER}_Firebase_Access_Json` | `firebase` (any variant: `sa`, `service`, `account`, `access`, `json`) |
| `jenkins` | `${USER}_Jenkins_Access_Token` | `jenkins` |

**1c. Resolution logic (per service):**

For each service in the table above, follow this order:

1. **Check standard key** -> `~/.copilot/lib/credential-store.sh get "<standard_key>" 2>/dev/null`
   - Found -> auto-map, done
2. **Search discovered keys** -> filter `$DISCOVERED` by the service's search keywords (case-insensitive)
   - Exactly 1 match -> show: `"Found '${matched_key}' for ${service}  -  use this? (enter=yes / n=skip)"` -> if yes, map it
   - Multiple matches -> show numbered list, user picks:
     ```
     Multiple keys found for GitHub:
       1. ${USER}_Github
       2. ${USER}_Github_Access_Token_Old
       3. ${USER}_Github_Access_Token
     Select [number] or skip:
     ```
   - 0 matches -> MISSING

**1d. Check preferences for existing mapping:**

Before running discovery, check `prefs.global.keychainMapping`. If a mapping already exists for a service AND the mapped key still exists in Keychain -> skip discovery for that service (show as already mapped from preferences).

If a previously mapped key NO LONGER exists in Keychain -> clear the stale mapping, re-run discovery for that service.

### Step 2  -  Show Discovery Summary + Save Mapping

Show results grouped by status:

```
Keychain Token Discovery (${USER}):

  Jira               -> ${USER}_Jira_Access_Token
  GitHub             -> ${USER}_Github
  Figma              -> ${USER}_Figma_Access_Token
  Firebase           -> ${USER}_Firebase_Access_Json
  Confluence         -> MISSING
  Jenkins            -> MISSING
  ---
  Git identities: check preferences file (see Step 3)

  Mapped: 8 | Missing: 4
```

Save the resolved mapping to preferences:
```json
{
  "global": {
    "keychainMapping": {
      "jira": "${USER}_Jira_Access_Token",
      "bitbucket_token": "${USER}_Bitbucket_Access_Token",
      "bitbucket_user": "${USER}_Bitbucket_Username",
      "github": "${USER}_Github",
      "confluence": null,
      "figma": "${USER}_Figma_Access_Token",
      "figma_mcp": "${USER}_Figma_Mcp_Access_Token",
      "fortify": null,
      "firebase": "${USER}_Firebase_Access_Json",
      "jenkins": null
    }
  }
}
```

`null` = not mapped (missing or skipped). Pipeline phases read this mapping to retrieve tokens dynamically  -  never hardcoded key names.

### Step 3  -  Jira Project Key (auto-learned)

Jira project keys are NOT asked during setup. They are auto-learned from pipeline usage:
- User runs `/multi-agent ABC-123` → `ABC` is extracted and saved to `prefs.global.defaultJiraKey` (first ever) and `prefs.projects[{project}].jiraProjectKeys` (per-project).
- User later runs `/multi-agent MOBILE-456` in a different project → `MOBILE` is added to that project's keys.
- Multiple keys accumulate over time  -  most recent first, deduped.

Phase 0 Step 1 (Parse Input) handles extraction and persistence. No setup interaction needed.

### Step 4  -  Git Identity Setup (one-time)

Git identities are NOT secrets  -  stored in the preferences file, not Keychain:

```bash
PREFS_FILE="$HOME/.claude/multi-agent-preferences.json"
```

If no identities exist in `prefs.global.gitIdentities` (first run):
```
Let's set up git identity.

Identity 1 (corporate):
  Author name: ___
  Email: ___
```

After each identity, ask with a native `AskUserQuestion` picker (never a typed y/n):
- `question`: "Add another git identity?" (rendered in `outputLanguage`)
- `header`: "Identity" (English, <=12 chars)
- `options`:
  - `{ label: "Add another", description: "Collect one more name + email identity" }`
  - `{ label: "Done", description: "Finish identity setup and save" }`

**Add another** → collect the next identity (e.g. Identity 2, personal: author name + email), then re-ask. **Done** → save.

Save to preferences JSON:
```json
{
  "global": {
    "gitIdentities": [
      {"name": "AUTHOR_NAME", "email": "AUTHOR_EMAIL"},
      {"name": "AUTHOR_NAME_2", "email": "AUTHOR_EMAIL_2"}
    ]
  }
}
```

Show result:
```
Git Identities (saved to preferences):
  1. {Full Name - Organization} <{corporate@email.com}>
  2. {Full Name} <{personal@email.com}>
```

### Step 5  -  Interactive token onboarding (for missing tokens)

For each MISSING service, run the **Token Save Flow** (see `setup.md` for full spec).

Summary: ask `[1] Add now / [2] Skip` → if add, user copies token to clipboard, presses Enter → pipeline reads from clipboard via `pbpaste`, saves to Keychain, clears clipboard. Token never appears in terminal.

The same flow is reused at Phase 0 runtime when a token is expired (401/403).

### Step 6  -  Verify all

Re-run scan from Step 1. Show final status:
```
All tokens present. Pipeline ready to use.

Optional per-project features (configured on first use, nothing to do now):
  • Phase 7 Report Step 2 Wiki  -  auto-generates component wiki pages + Figma
    screenshots. Activates when (a) task is a component AND (b) a Figma token
    is in Keychain. Four adapters supported: submodule / in-repo / github-wiki
    / separate-repo. First run asks: use auto-detected path, use a custom
    path, skip once, or disable for this project (persisted).
  • channels  -  post-hoc multi-channel reporter (Jira/Confluence/Wiki/PR), works on any branch with an open PR. v5.7+ replaces the older `enrich` command.
  • Default reviewers  -  auto-fetched from Bitbucket default-reviewers endpoint
    or GitHub CODEOWNERS on first PR.

Next step:
  /multi-agent "PROJ-12345"              -> start your first task
  /multi-agent help                      -> full usage guide
```

If still missing, show which ones and let user skip (pipeline will re-ask for any needed token at Phase 0).

### Token -> Source Mapping

Standard key names (used when creating NEW tokens). Discovery may find existing keys under different names  -  that's fine, the mapping in preferences handles it.

| Service ID | Standard Key Name | Type | Where to Get |
|------------|------------------|------|---------------|
| `jira` | `${USER}_Jira_Access_Token` | PAT | Jira -> Profile -> Personal Access Tokens (VPN required) |
| `bitbucket_token` | `${USER}_Bitbucket_Access_Token` | App Password | Bitbucket -> Personal settings -> App passwords |
| `bitbucket_user` | `${USER}_Bitbucket_Username` | Plain text | Bitbucket profile username |
| `github` | `${USER}_Github_Access_Token` | PAT | GitHub Settings -> Tokens (scopes: repo, read:org, project) |
| `confluence` | `${USER}_Confluence_Access_Token` | PAT | Confluence -> Profile -> Personal Access Tokens (VPN required) |
| `figma` | `${USER}_Figma_Access_Token` | PAT | Figma Developer Settings (max 90 days) |
| `figma_mcp` | `${USER}_Figma_Mcp_Access_Token` | OAuth | Automatic via Claude Code Figma MCP remote auth |
| `fortify` | `${USER}_Fortify_Access_Token` | API Token | Fortify SSC -> Token Management (VPN required) |
| `firebase` | `${USER}_Firebase_Access_Json` | Firebase JSON (base64) | Firebase Console -> Project settings -> Service accounts -> Generate new private key. Project id is parsed from the decoded JSON. |
| `jenkins` | `${USER}_Jenkins_Access_Token` | API Token | Jenkins -> User -> Configure -> API Token |
|  -  | Git Identities | JSON (preferences) | Stored in `$HOME/.claude/multi-agent-preferences.json`  -  not Keychain |

### Inline Token Save Pattern

All tokens go through `~/.copilot/lib/credential-store.sh`, which auto-delegates to `~/.copilot/scripts/keychain.py` on macOS / Linux and the PowerShell `CredentialManager` module on Windows. The Python path writes both `-l` (label) and `-s` (service) attributes so existing manually-added entries with either convention remain findable.

```bash
# PAT / API Key (from clipboard)
pbpaste | ~/.copilot/lib/credential-store.sh set "<SERVICE_NAME>" "$(cat)"
pbcopy < /dev/null  # clear clipboard

# Plain text (direct value)
~/.copilot/lib/credential-store.sh set "<SERVICE_NAME>" "<VALUE>"

# JSON file (base64 encode)
~/.copilot/lib/credential-store.sh set "<SERVICE_NAME>" "$(base64 < /path/to/file.json)"

# Read
~/.copilot/lib/credential-store.sh get "<SERVICE_NAME>"

# Decode JSON
~/.copilot/lib/credential-store.sh get "<SERVICE_NAME>" | base64 -d
```

For maximum stdin hygiene (the secret never lands on argv / shell history), use the Python helper directly with the `-` sentinel:

```bash
pbpaste | ~/.copilot/scripts/keychain.py set "<SERVICE_NAME>" -
```

### Figma MCP Setup (optional)

Figma MCP works in two modes:

**Remote MCP** (Claude Code built-in):
- Automatic  -  comes as `claude_ai_Figma` in Claude Code settings.json
- If token renewal needed: re-auth from within Claude Code

**Local MCP** (@anthropic-ai/figma-mcp package, with PAT):
```bash
# 1. Save PAT to keychain
security delete-generic-password -a "$USER" -s "${USER}_Figma_Access_Token" 2>/dev/null
security add-generic-password -a "$USER" -s "${USER}_Figma_Access_Token" -w "$(pbpaste)"
pbcopy < /dev/null

# 2. Add MCP to Claude Code settings.json
# ~/.claude/settings.json -> mcpServers -> figma
```

### App Store Connect Credentials (optional, iOS only)

Unlocks Gate 2 of `multi-agent-testflight-validation`  -  Apple's own
`altool --validate-app`, the only check that sees an unregistered bundle ID, a
profile that does not match the App Store Connect app record, or a version+build
pair already used. Skipping is a first-class answer: the validation command still
runs its static audit and guideline review and reports Gate 2 as `SKIPPED` with
the reason, never as a pass.

Ask (picker): **API key** / **Apple ID + app-specific password** / **Skip**.

**API key**  -  needs an Admin or App Manager role in App Store Connect. Map the key
id and issuer id as `appstore_connect_key_id` / `appstore_connect_issuer_id`. The
private key is a FILE and never enters the credential store; it goes to one of the
directories altool searches:

```bash
ls ~/.appstoreconnect/private_keys/AuthKey_*.p8 2>/dev/null \
  || echo "MISSING: put AuthKey_<keyId>.p8 in ~/.appstoreconnect/private_keys/"
```

**Apple ID + app-specific password**  -  usable by **any Apple ID holder, no elevated
role**, which is the realistic path when API-key creation is not permitted on the
account. Lead with this option when the user says they cannot create an API key.
The password goes into Apple's own keychain helper, which is what
`altool -p @keychain:<item>` reads  -  never into chat, never into an argument:

```bash
# export AC_PASSWORD_ONCE in your own shell first, for this one command
xcrun altool --store-password-in-keychain-item "<item-name>" \
  -u "<apple-id>" -p @env:AC_PASSWORD_ONCE
```

Map only the ITEM NAME as `appstore_connect_password_item`, plus the Apple ID as
`appstore_connect_apple_id`. The password stays in the keychain and is referenced,
never read by the pipeline.

**Multi-provider accounts.** A corporate Apple ID often belongs to several
providers and altool fails opaquely without one. Resolve it once with
`ios_testflight_validate({list_providers: true, ...})` and store the id under
`prefs.projects[<key>].appStoreConnect.providerPublicId`  -  per-project, since a
user can ship for more than one team.

A credential that resolves but is rejected (401/403) follows the Expired-token
decision (Regenerate / Use a different token / Skip and continue) rather than
being silently dropped.

### Security Rules

- Never paste tokens into terminal or chat  -  use `pbpaste` for input
- Never hardcode tokens in source code
- Never commit tokens to git history
- Clear clipboard immediately: `pbcopy < /dev/null`
- `2>/dev/null` suppresses stderr (prevents metadata leakage)

### Setup from Scratch Summary

To set up multi-agent on a new machine:

```
1. Install the toolkit:
   npx @mmerterden/multi-agent-pipeline install

2. Start setup:
   /multi-agent setup

3. Interactive flow:
   -> Token scan (shows what is missing)
   -> Git Identity creation (name + email)
   -> Inline commands for missing tokens
   -> Final verification

4. Ready:
   /multi-agent "PROJ-12345"
   /multi-agent "https://github.com/.../issues/42"
   /multi-agent "bug description"
```

All tokens are optional  -  pipeline will ask for any needed token at Phase 0. Setup only does pre-preparation.
