# gw-triage — Codex CLI support Date: 2026-07-10 Status: approved ## Problem The plugin only runs under Claude Code: distribution relies on the Claude plugin marketplace, skills locate their data via `${CLAUDE_PLUGIN_ROOT}`, Jira access goes through the Atlassian MCP plugin, and credentials live in the `env` block of `~/.claude/settings.json`. Teammates on OpenAI Codex CLI can't use any of it. Goal: full parity — `triage`, `setup`, and `map-repo` all work on Codex, from the same repo, with no duplicated skill files. ## Decisions (agreed 2026-07-10) 1. **Scope**: full parity for all three skills. 2. **Jira transport on Codex**: plain REST via curl with the Jira API token. No MCP configuration on Codex. Claude Code keeps its MCP path unchanged. 3. **Skill files**: one SKILL.md per skill, shared by both platforms, branching internally where behavior differs. 4. **Credentials**: a single netrc file at `~/.config/gw-triage/netrc` used by curl on both platforms, replacing the settings.json env block as the primary store. ## Verified platform facts - Codex discovers skills in `.agents/skills` (project, walking up to repo root) and `~/.agents/skills` (user level). Symlinked skill directories are followed. - Skills use the same SKILL.md format (frontmatter `name` + `description`); invoked explicitly as `$` or implicitly via the description. - Codex's `[shell_environment_policy]` env injection filters names containing `TOKEN` by default and has open reliability issues — ruled out in favor of the netrc file. - Jira Cloud REST API v2 (`/rest/api/2/…`) is still served and accepts plain-text descriptions, avoiding the ADF JSON required by v3 `createIssue`. v2 is legacy; if Atlassian retires it, the REST-mode steps move to v3 + minimal ADF paragraphs. ## Design ### 1. Distribution Repo structure unchanged. Codex users clone the repo anywhere and symlink each skill directory into `~/.agents/skills/`: ~/.agents/skills/triage -> /skills/triage ~/.agents/skills/setup -> /skills/setup ~/.agents/skills/map-repo -> /skills/map-repo A small `install-codex.sh` at the repo root creates/refreshes the symlinks idempotently. Updates arrive with `git pull` in the clone. Skill names stay as-is so Claude Code commands don't change (`/gw-triage:triage`). On Codex they are `$triage`, `$setup`, `$map-repo`; the generic names could collide with other installed skills — accepted risk for a three-person team, noted in the README. ### 2. Platform detection and root resolution Each SKILL.md gets a short "Environment" preamble: - **Root**: `${CLAUDE_PLUGIN_ROOT}` if set; otherwise resolve the real path (symlinks followed) of the skill's own directory and go up two levels. `config/` and `knowledge/` are addressed relative to that root everywhere. - **Mode** (triage only): Atlassian MCP tools available → MCP mode (today's behavior, unchanged); otherwise → REST mode. ### 3. Credentials — netrc file `setup` writes `~/.config/gw-triage/netrc`: machine growingway.atlassian.net login password (machine host derived from `site` in routing.json), `chmod 600`. Every curl call on both platforms passes `--netrc-file ~/.config/gw-triage/netrc`, read at call time — no session restart needed after setup, and no secrets on command lines or in process listings. `setup` itself becomes platform-neutral (file operations + curl only): - Verify pasted credentials against `GET /rest/api/2/myself` before saving (3-attempt limit, network-vs-auth error distinction — as today). - **Migration**: if credentials already exist in the session env or in `~/.claude/settings.json` `env`, verify them and migrate them into the netrc automatically; suggest removing the settings.json entries (leftover shell-profile check stays). - The temp-netrc-for-literals dance disappears: the real netrc file IS the store, written before verification and deleted only if verification ultimately fails. `triage` reads the netrc as the primary credential source and falls back to `JIRA_EMAIL`/`JIRA_API_TOKEN` env vars (legacy installs) for the attachment step. ### 4. Triage in REST mode Used on Codex. (Claude Code without MCP still stops and points at the Atlassian plugin install, as today — MCP remains the intended path there.) On Codex the token is **required** — it is the only transport. Missing or invalid netrc → stop with `$setup` instructions. | Step | MCP mode (unchanged) | REST mode | |---|---|---| | Preflight | `getAccessibleAtlassianResources` | `GET /rest/api/2/myself` → expect 200 | | Duplicate search | `searchJiraIssuesUsingJql` | `GET /rest/api/3/search/jql?jql=` (the v2/v3 `/search` endpoints were removed by Atlassian in 2025) | | Create | `createJiraIssue` | `POST /rest/api/2/issue` (JSON body: project, issuetype, summary, plain-text description, assignee accountId, parent epic) | | Comment on duplicate | `addCommentToJiraIssue` | `POST /rest/api/2/issue/{key}/comment` | | Attach screenshot | curl (as today) | same curl, `--netrc-file` | `cloudId` in routing.json becomes MCP-only; REST mode uses `site`. Classification, drafting, confirmation flow, and Italian interaction are identical in both modes. ### 5. map-repo Two touch-ups: - Root resolution per §2 (replaces `${CLAUDE_PLUGIN_ROOT}`). - Survey step: "dispatch one exploration subagent **if the platform supports subagent dispatch; otherwise perform the survey yourself**, covering the same six points." - Publish step: note that Codex teammates receive updates with `git pull` in their clone (Claude Code users keep `/plugin marketplace update gw-triage`). ### 6. README - New "Installazione (Codex)" section: clone, `./install-codex.sh`, run `$setup`, daily use via `$triage`. - Token section updated: netrc path, token optional on Claude Code (attachments only), **required** on Codex. - Per-platform update instructions and troubleshooting entries. ## Error handling - REST calls: treat non-2xx as failure; show the raw body with a one-line Italian summary. Create-issue failure stops before the attachment step (nothing partial), as today. - Netrc unreadable/missing on Codex → stop with setup guidance; on Claude Code → warn once that attachment will be skipped, proceed. - JQL must be URL-encoded in REST mode (curl `--data-urlencode` with `-G`). ## Testing - REST commands exercised directly against Jira: `myself`, JQL search, create on a throwaway issue, comment, attachment — then delete the throwaway. - Codex smoke test: skills discovered after `install-codex.sh`, `$triage` dry run reaches the draft step, `$setup` full run. - Claude Code regression: `/gw-triage:triage` full run with netrc in place (MCP mode + netrc attachment), `/gw-triage:setup` migration path from settings.json env vars. ## Out of scope - Renaming skills or namespacing for Codex. - Moving Claude Code off MCP. - Windows support (team is on macOS). - v3/ADF migration (documented as future work if v2 is retired).