docs: design for Codex CLI support
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
172
docs/codex-support-design.md
Normal file
172
docs/codex-support-design.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# 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 offer to migrate
|
||||
them into the netrc; 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/2/search?jql=<urlencoded>` |
|
||||
| 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).
|
||||
Reference in New Issue
Block a user