173 lines
6.9 KiB
Markdown
173 lines
6.9 KiB
Markdown
# 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 `$<name>` 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 -> <clone>/skills/triage
|
|
~/.agents/skills/setup -> <clone>/skills/setup
|
|
~/.agents/skills/map-repo -> <clone>/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 <email>
|
|
password <token>
|
|
|
|
(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=<urlencoded>` (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).
|