{"id":50728322,"url":"https://github.com/applied-artificial-intelligence/relay","last_synced_at":"2026-06-10T06:02:48.790Z","repository":{"id":362403514,"uuid":"1252517007","full_name":"applied-artificial-intelligence/relay","owner":"applied-artificial-intelligence","description":"Cross-agent (Claude Code + Codex) planning \u0026 execution workflow: align → plan → project → implement → ship. Local-first work units, GitHub as projection (epic → milestones → issues).","archived":false,"fork":false,"pushed_at":"2026-06-04T04:36:49.000Z","size":122,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-04T05:12:04.684Z","etag":null,"topics":["agent-workflow","ai-agents","claude-code","codex","coding-agents","developer-tools","github-projects","llm","project-planning"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/applied-artificial-intelligence.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-28T15:45:03.000Z","updated_at":"2026-06-04T04:36:52.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/applied-artificial-intelligence/relay","commit_stats":null,"previous_names":["applied-artificial-intelligence/relay"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/applied-artificial-intelligence/relay","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/applied-artificial-intelligence%2Frelay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/applied-artificial-intelligence%2Frelay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/applied-artificial-intelligence%2Frelay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/applied-artificial-intelligence%2Frelay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/applied-artificial-intelligence","download_url":"https://codeload.github.com/applied-artificial-intelligence/relay/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/applied-artificial-intelligence%2Frelay/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34139186,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-workflow","ai-agents","claude-code","codex","coding-agents","developer-tools","github-projects","llm","project-planning"],"created_at":"2026-06-10T06:02:47.993Z","updated_at":"2026-06-10T06:02:48.784Z","avatar_url":"https://github.com/applied-artificial-intelligence.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Relay\n\n**A cross-agent (Claude Code + Codex) planning/execution workflow.** Portable\noperating discipline + continuity across agents: forcefully align on a spec, plan it\nunder a mechanically-bounded agent that *can't* run off and build, project it onto\nGitHub (epic → milestones → issues), then implement and ship incrementally.\n\nLocal docs are the source of truth; **GitHub is the projection** (degrades to\nlocal-only with no remote). One workflow, two host bindings — both converge on the\nsame `.workspace/work/\u003cunit\u003e/` files and `gh` projection.\n\n\u003e **Status**: alpha — pipeline complete (all 5 steps live-tested), published\n\u003e to PyPI as [`relay-workflow`](https://pypi.org/project/relay-workflow/) 0.1.0\n\u003e (2026-06-03). Extracted 2026-05-28 from `factory` work unit 024\n\u003e (`claude_codex_interop_framework`). Successor to the Claude-only\n\u003e `claude-code-toolkit` (which remains active separately). Design rationale\n\u003e and the empirical host probes are in [`docs/`](docs/).\n\u003e\n\u003e **See it run**: [`docs/demo.cast`](docs/demo.cast) — a recorded\n\u003e end-to-end pipeline against a fresh GitHub repo\n\u003e ([`applied-artificial-intelligence/relay-demo`](https://github.com/applied-artificial-intelligence/relay-demo)):\n\u003e `relay plan` → `relay project --execute` → `relay implement --execute`\n\u003e (headless Claude writes `greet.py`) → `relay ship --execute` (PR #8\n\u003e merged). Play with `asciinema play docs/demo.cast`.\n\n## Pipeline (host-neutral)\n\nFive steps built — pipeline complete:\n\n```\nalign/    →  spec.md       forceful interrogation (skill + Codex prompt; interactive)\nrelay_plan.py      →  plan.json/.md   bounded plan-only agent run (can't implement)\nrelay_project.py   →  GitHub          idempotent epic + milestones + issues (+ branches)\nrelay_implement.py →  branch + PR     headless agent implements one issue (Closes #)\nrelay_ship.py      →  merged PR       bubble up issue/milestone/project state\n```\n\nAlongside the pipeline, **`relay compile`** is a small adjacent tool that\nsolves the *other* cross-agent problem: author a skill once in a canonical\nSKILL.md and emit both `.claude/skills/\u003cname\u003e/` (full frontmatter) and\n`.agents/skills/\u003cname\u003e/` (Codex-trimmed, with a `SKILL_DIR` resolver). See\n[`docs/skill-format.md`](docs/skill-format.md).\n\n## `align/` — spec interrogation (interactive)\n\n`align/SKILL.md` (Claude skill) + `align/align.codex.md` (Codex `/align` prompt):\nforcefully interrogate the user — one question at a time, challenge vague answers,\nforce out-of-scope exclusions — then write `\u003cunit\u003e/spec.md` from `spec-template.md`.\nFront-loads all human clarification so the headless `plan` step never needs to ask.\nDeploy: copy `SKILL.md` to a skills dir; copy `align.codex.md` to `~/.codex/prompts/align.md`.\n\n## `relay_plan.py` — plan step\n\n`relay_plan.py`: turns an aligned **spec** into a structured, milestone/issue\n**plan** without letting the coding agent run off into implementation. Host-neutral.\n\n```\nspec.md  →  [bounded plan-only agent run]  →  plan.json + plan.md\n```\n\n1. Reads `\u003cunit\u003e/spec.md` (produced by `align`).\n2. Runs the host's **mechanically bounded \"plan-but-don't-build\" primitive**:\n   - **Claude**: `claude -p --permission-mode plan` — `ExitPlanMode` is terminal,\n     nothing executes. Plan extracted from `--output-format json` result (falls back\n     to newest `~/.claude/plans/*.md`).\n   - **Codex**: `codex exec --sandbox read-only --output-schema \u003cschema\u003e -o \u003cfile\u003e` —\n     read-only sandbox can't write; schema **enforces** the milestone/issue JSON shape.\n3. Writes `\u003cunit\u003e/plan.json` (structured) + `\u003cunit\u003e/plan.md` (human/checklist).\n4. Emits `\u003cunit\u003e/gh_projection.sh` — a flat, non-idempotent `gh` script. **Superseded\n   by `relay_project.py`** for real use; kept only as a quick-look dry-run.\n\n## `relay_project.py` — project step (idempotent GitHub projection)\n\nMirrors `plan.json` onto GitHub: a tracking **epic** issue, **milestones**, one\n**issue** per work item, with branch + `Closes #` wiring written back into `plan.json`.\n\n```\nplan.json  →  [resolve repo]  →  epic + milestones + issues  →  plan.json (numbers+branches) + projection.json\n```\n\n- **Idempotent**: matches existing milestones/issues by title (`gh api .../milestones`,\n  `gh issue list`) and reuses them — re-running never duplicates. Verified live against\n  a throwaway repo (4 milestones/21 issues; second run created 0 new objects).\n- **Epic**: a `[epic] \u003cobjective\u003e` tracking issue with a child task-list, refreshed\n  (not duplicated) on re-run. `--no-epic` to skip.\n- **Branch/PR wiring**: each issue gets `branch: relay/m\u003cn\u003e-\u003cmslug\u003e/\u003cislug\u003e` and a\n  `Closes #\u003cn\u003e` contract recorded in `plan.json` for IMPLEMENT to consume.\n- **Local-first**: no GitHub remote → exits local-only (add a remote and re-run to promote).\n- **Missing labels** don't abort — the issue is created without them and logged.\n\n## `relay_implement.py` — implement step (headless, one issue → PR)\n\nConsumes the projected `plan.json` and drives a **headless coding agent** to\nimplement ONE issue on its branch, then opens a PR that closes the issue. This is\nthe step that lets Relay execute its own backlog instead of a human hand-building.\n\n```\nplan.json  →  [select issue]  →  branch off base  →  [headless agent]  →  push + PR (Closes #N)  →  plan.json (pr+state)\n```\n\n- **One issue at a time** (workflow-design.md model). Default target = first\n  *pending* issue (state ∉ {implemented, merged, done}); `--issue \u003c#n|title\u003e` to pick.\n- Reuses the `branch`/`closes` wiring the PROJECT step wrote into `plan.json`\n  (errors if absent — run `relay_project.py --execute` first).\n- Assembles a **brief** from objective + milestone + issue body + `spec.md` (the\n  durable contract) + mechanical scope rules — host-neutral, byte-identical\n  across hosts — then runs the chosen host headless (Claude: `claude -p\n  --output-format json`; Codex: `codex exec` in a `workspace-write` sandbox).\n  Success is verified by `git` (commits on the branch), not by parsing stdout.\n- **Idempotent**: reuses an existing branch / existing PR; if the agent leaves no\n  commits, records `state=no-op` and opens no PR. Local-only (no remote) →\n  `state=implemented-local`, branch left for later promotion.\n- **Dry-run by default**: prints target, branch, the commands it would run, and the\n  full assembled brief. `--execute` to branch + spend an agent run + open the PR.\n- **Host: `--host {claude,codex,auto}`** (default `auto`). Auto-detect mirrors\n  PLAN's precedence — `claude` on PATH wins, else `codex`, else a clear error.\n  Both hosts drive the same host-neutral brief and write the same `state`\n  vocabulary (`open` / `no-op` / `implemented-local`).\n- **Host equivalence**: Codex runs under a `workspace-write` sandbox so it can\n  edit and commit the working tree. (PLAN uses `read-only` for a *different*\n  reason — to mechanically bound the planner so it can't build; IMPLEMENT must\n  be able to write.) For fully-autonomous runs that must run tests and commit\n  without prompts, `codex --dangerously-bypass-approvals-and-sandbox` is the\n  analogue of Claude's `--permission-mode bypassPermissions` (default is the\n  safer `acceptEdits`).\n\n## `relay_ship.py` — ship step (incremental: PR merge → issue/milestone done)\n\nConsumes the `pr`/`state` IMPLEMENT wrote into `plan.json` and **closes the loop\nincrementally**. There is no terminal \"ship\" event in workflow-design.md — SHIP\nruns (and re-runs) as PRs become mergeable: PR merge → issue done (auto via\n`Closes #N`) → milestone done (when all its issues are merged) → project done\n(when every milestone closes).\n\n```\nplan.json  →  [pick PR]  →  check mergeable + checks  →  gh pr merge  →  bubble-up  →  plan.json (merged/done)\n```\n\n- **One PR per run by default** (mirrors IMPLEMENT's one-at-a-time); `--all` to\n  drain every mergeable PR in one pass.\n- Merge gate: `mergeable=MERGEABLE` AND checks not `FAILING`. Pending checks\n  block by default; `--auto` enables GitHub auto-merge so the PR lands when\n  checks pass.\n- `--admin` bypasses branch protections on repos without CI.\n- `mergeable=UNKNOWN` (GitHub's lazy-compute response on first probe) is\n  auto-retried once.\n- After each pass, bubbles up milestones whose issues are all done and sets\n  `plan.state = \"shipped\"` when every milestone closes.\n- `gh pr merge` lands on GitHub leaving the local base behind — SHIP fetches +\n  fast-forwards before committing state so the push succeeds the first time.\n- Already-merged PRs are recognised and reconciled without re-merging\n  (re-running is safe + idempotent).\n\n## `relay compile` — author skills once, emit both host variants\n\nThe pipeline is *workflow* interop; this is *artifact* interop. Same problem\nshape (one source, two hosts), different surface.\n\n```\nskills-src/\u003cname\u003e/SKILL.md  →  .claude/skills/\u003cname\u003e/   (full frontmatter, ${CLAUDE_SKILL_DIR})\n                            →  .agents/skills/\u003cname\u003e/   (name+description only, ${SKILL_DIR} resolver)\n```\n\n- Canonical SKILL.md is the **Claude-superset**: write at the richer level,\n  the compiler drops Claude-only frontmatter fields when emitting Codex.\n- Self-references use `{baseDir}` (the form Claude skills already use). The\n  compiler rewrites it to `${CLAUDE_SKILL_DIR}` for Claude and to\n  `${SKILL_DIR}` for Codex, and injects a one-line resolver into the first\n  bash block on the Codex side so `SKILL_DIR` is always defined.\n- `@import ./file.md` becomes an on-demand `Read` reference for Claude\n  (progressive disclosure) and is *inlined* verbatim for Codex (which has\n  no include mechanism).\n- Codex output carries an `AUTO-GENERATED … do not edit` header so a future\n  hand-editor doesn't change the wrong file.\n- Bundled assets (`scripts/`, `references/`, etc.) are copied verbatim to\n  both outputs.\n- Lints on Codex's caps (`name ≤ 64`, `description ≤ 1024`).\n\nFormat details and rationale: [`docs/skill-format.md`](docs/skill-format.md).\nFunctionally verified on real marketplace skills (`lightgbm-training`,\n`structured-writing`, …).\n\n## `relay sync` — bulk-install a marketplace's skills into Codex user-scope\n\n`compile` works on one source dir. `sync` is the obvious wrapper: walk an\nentire plugin marketplace and install every skill into Codex's user-scope\nskills dir, so Codex sees the same library Claude does.\n\n```\n~/agents/coding/plugins/*/skills/\u003cname\u003e/SKILL.md\n       │\n       └─ relay sync ──→ ~/.codex/skills/\u003cname\u003e/        (Codex-trimmed + ${SKILL_DIR})\n```\n\n- **Codex-only by default**. Marketplace plugins are already in Claude form,\n  and Claude's plugin mechanism makes them visible when the plugin is\n  enabled in `.claude/settings.json`. Codex has no plugin mechanism, so a\n  user-scope install is its only path to the same skills.\n- **Dry-run by default** (mirrors `relay project / implement / ship`).\n  `--execute` to actually emit.\n- **Idempotent**: per-skill `\u003ctarget\u003e/\u003cname\u003e/` is fully replaced on each\n  run; unrelated neighbour skills in the target dir are untouched.\n- **Collision-aware**: same skill-name in two plugins gets flagged on\n  stderr (last write wins).\n- **Filters**: `--plugin \u003cname\u003e` to limit, `--marketplace \u003cdir\u003e` /\n  `--target \u003cdir\u003e` to override defaults.\n\n```bash\nrelay sync                                              # dry-run, defaults\nrelay sync --execute                                    # install every skill into ~/.codex/skills/\nrelay sync --plugin quant --execute                     # just the quant plugin's skills\nrelay sync --marketplace ~/my-plugins --target ~/.codex/skills --execute\n```\n\n## Install\n\nFrom PyPI:\n```bash\nuv tool install relay-workflow   # recommended (isolated env, like pipx)\n# or\npipx install relay-workflow      # legacy-compatible alternative\n```\n\nFrom source (for development or to pin to a working tree):\n```bash\ngit clone https://github.com/applied-artificial-intelligence/relay\ncd relay\nuv tool install --force .        # install this checkout\n```\n\nBoth paths put a `relay` binary on your `PATH`. Requires Python ≥ 3.10 and the\n`gh` CLI for the steps that touch GitHub.\n\n## Usage\n\n```bash\n# align: invoke the Claude skill / Codex /align prompt (interactive), then:\nrelay plan \u003cwork-unit-dir\u003e                            # auto-detect host, plan only\nrelay plan \u003cunit\u003e --host codex                        # force host\nrelay project \u003cunit\u003e                                  # dry-run GitHub projection\nrelay project \u003cunit\u003e --execute                        # create/refresh epic+milestones+issues\nrelay implement \u003cunit\u003e                                # dry-run: show target issue + brief\nrelay implement \u003cunit\u003e --execute                      # implement first pending issue → PR (auto-detect host)\nrelay implement \u003cunit\u003e --host codex --execute         # force Codex as the headless coding host\nrelay implement \u003cunit\u003e --issue 7 --execute --permission-mode bypassPermissions\nrelay ship \u003cunit\u003e                                     # dry-run: which PRs would merge\nrelay ship \u003cunit\u003e --all --execute                     # merge every mergeable PR, bubble up\nrelay ship \u003cunit\u003e --execute --auto                    # enable auto-merge (wait on checks)\n\nrelay compile \u003cskills-src-dir\u003e \u003cout-dir\u003e              # one SKILL.md → both .claude/ and .agents/\nrelay sync                                            # dry-run: list marketplace skills → ~/.codex/skills/\nrelay sync --execute                                  # install all marketplace skills into Codex user-scope\n```\n\n`relay --help` lists steps; `relay \u003cstep\u003e --help` lists step-specific options.\n`python -m relay \u003cstep\u003e` works too (handy on systems where `pipx`/`uv`-installed\nscripts aren't on `PATH` yet).\n\n## Verified (2026-05-27)\n\n| Host | Mechanism | Output | Time | Repo touched? |\n|---|---|---|---|---|\n| Codex (gpt-5.5) | PLAN: read-only + enforced schema | 4 milestones / 21 issues | 39s | no |\n| Claude (2.1.152) | PLAN: `--permission-mode plan` + JSON extract | 2 milestones / 10 issues | 29s | no |\n| Claude IMPLEMENT | `claude -p` in working tree | 2 issues → 2 PRs (`Closes #`) | — | yes (commits on branch) |\n| Codex IMPLEMENT | `codex exec` + `workspace-write` sandbox | branch + PR (`Closes #`) — _pending live verification_ | — | yes (commits on branch) |\n\nBoth leave the repo untouched (the anti-runaway guarantee is mechanical, not\nbehavioral) and converge on the same `plan.json` + `gh_projection.sh`.\n\n## Known gaps (prototype, not production)\n\n- **Codex schema** requires `additionalProperties:false` + every property in\n  `required` (OpenAI structured-output rule) — handled in `PLAN_SCHEMA`.\n- Claude path is **not** schema-enforced — relies on the model returning JSON; a\n  structuring/repair pass would harden it.\n- No rolling-wave support yet (re-plan a single milestone into issues later).\n- GitHub **Projects v2** board (Status/Area/Type fields, à la tradesharp) is not\n  created — `relay_project.py` does epic issue + milestones only (CLI-friendly, no\n  GraphQL). Project-v2 wiring is the next projection increment.\n- Issue-level idempotency matches on **exact title**; renaming an issue in the spec\n  creates a new one rather than updating the old. Acceptable for append-style planning.\n- **IMPLEMENT `--execute` live-tested 2026-05-28** (throwaway `relay-smoketest`, 2 issues →\n  2 PRs via `claude -p`, both in-scope with tests + correct `Closes #`). Idempotency holds:\n  skips issues that already have a PR (`--redo` to force), state is committed to the base\n  branch (survives between runs, leaves a clean tree), dirty-guard ignores untracked agent\n  artifacts. Default selection walks pending issues one at a time.\n- **Parallel issues on one file conflict at merge time**: each issue branches off base\n  independently, so two issues editing the same file produce mergeable-but-conflicting PRs.\n  That's a SHIP/rebase concern, not a runner bug.\n- **SHIP `--execute` live-tested 2026-05-31** (same `relay-smoketest` repo): merged PR #4\n  (`Closes #1` auto-closed issue #1), correctly detected the parallel-PR conflict on PR #5,\n  bubble-up left milestone open (1 of 2 issues done). Already-merged reconciliation verified\n  on a second pass after a hard reset. Fixed two bugs found during the live test:\n  (a) `gh pr view` first probe returning `mergeable=UNKNOWN` — auto-retry once;\n  (b) post-merge local base was stale, so state push failed — fetch + fast-forward before\n  committing state.\n\n## Repo layout\n\n```\nalign/             ALIGN step — Claude skill + Codex /align prompt + spec template\nsrc/relay/         Python package — installs as the `relay` CLI dispatcher\n  cli.py           subcommand dispatcher (relay plan|project|implement|ship)\n  plan.py          PLAN step  — bounded plan-only run → plan.json/.md\n  project.py       PROJECT step — idempotent GitHub epic/milestones/issues\n  implement.py     IMPLEMENT step — headless agent implements one issue → PR (Closes #)\n  ship.py          SHIP step — incremental PR merge → issue/milestone bubble-up\npyproject.toml     hatchling build; entry-point `relay = \"relay.cli:main\"`\ndocs/              workflow-design.md, planmode-probe.md, portal-briefing.md, PROPOSAL.md\n.workspace/        agent state (memory/transitions/work), interop convention\n```\n\n## Design \u0026 provenance\n\n- [`docs/workflow-design.md`](docs/workflow-design.md) — canonical workflow spec (ALIGN→PLAN→PROJECT→IMPLEMENT→SHIP).\n- [`docs/planmode-probe.md`](docs/planmode-probe.md) — Claude vs Codex plan-mode probe; the empirical basis for the bounded-planner design.\n- [`docs/portal-briefing.md`](docs/portal-briefing.md) — briefing for the website Agent Lab portal.\n- Next steps (from design): self-host Relay (run the full ALIGN→…→SHIP cycle on Relay's\n  own backlog), then rolling-wave re-planning + Projects v2 board.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapplied-artificial-intelligence%2Frelay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapplied-artificial-intelligence%2Frelay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapplied-artificial-intelligence%2Frelay/lists"}