# rubicon-codex-plugin
Coach workflow plugin for authoring and publishing [Rubicon](https://www.rubicon.fitness/)
training programming from [OpenAI Codex CLI](https://github.com/openai/codex).
## Why this exists
Today, getting training programming from a coach's Google Sheet into Rubicon
requires a human in the loop translating between the sheet and Rubicon's
Coach MCP Surface. This plugin retires that bridge: it's a public,
installable Codex plugin a coach points their own Codex at to walk through
reading their sheets, transforming them into Rubicon's programming graph
format, previewing the write, and publishing it — end to end, from their own
machine, using their own Rubicon coach login.
No one else's credentials, sheet IDs, or Rubicon session are involved. Each
coach who installs this plugin authenticates as themselves, against their
own sheets.
## Install
```sh
codex plugin marketplace add joelhooks/rubicon-codex-plugin --ref main
```
## First-run onboarding
On first install, an onboarding hook prompts you for your own:
- **Programming Source Sheet** (ID or full URL)
- **Movement Source Sheet** (ID or full URL)
These are saved locally to Codex's per-install plugin data directory
(`$PLUGIN_DATA/sheet-ids.json`) — **never** to this repository, and never to
any file the skills write back into a repo. Skills resolve the real sheet
IDs from that local file at runtime. If you ever need to change them, delete
`$PLUGIN_DATA/sheet-ids.json` and reinstall/re-trigger onboarding.
See `hooks/hooks.json` and `hooks/onboard-sheet-ids.sh` for the
implementation.
## The four-stage workflow
This plugin is deliberately split into four separate skills rather than one
mega-skill, so you can stop and review between every stage:
1. **`sheet-read`** — Pulls raw rows from the Programming Source Sheet
and/or Movement Source Sheet using [`gogcli`](https://github.com) (the
`gog` CLI), which authenticates via your own Google account through the
macOS keychain. Nothing is transformed yet — review the pulled rows
before continuing.
2. **`programming-inference`** — Transforms raw rows into Rubicon
programming write operations (`create_node` / `patch_node` /
`create_edge` / `patch_edge`), applying the conjugate-method coaching
conventions (Max Effort / Dynamic Effort / Repetition Effort) documented
in the skill, and resolving movement IDs via the `movement_catalog_search`
MCP tool instead of guessing. Batches are capped at 25 operations per
write call (server-enforced) — larger imports are split into multiple
batches. **Nothing is written to Rubicon yet.**
3. **`preview`** — Calls `programming_write_dry_run` on the Coach MCP
Surface with the operation batch. Returns a `confirmationToken` (computed
server-side, deterministic per exact operation set) and a preview of
what would change. **Review this before continuing — this is your last
checkpoint before anything is written.**
4. **`publish`** — Calls `programming_write_publish` with the *same*
operations and the `confirmationToken` from `preview`. The server
rejects the publish if the token doesn't match the exact operation set
that produced it — an existing hard safety gate on Rubicon's side, not
something this plugin adds.
Stop between any two stages to sanity-check the output. Nothing downstream
of `sheet-read` runs automatically.
## Security model
- **No credentials or sheet identity are ever committed to this repo.**
Not in a skill file, not as an "example," not in a config default.
Real-looking spreadsheet IDs/URLs never appear here, even as placeholders
— placeholders use obviously-fake tokens like `<PROGRAMMING_SOURCE_SHEET_ID>`.
- Skills refer to the two sheets only by name ("the Programming Source
Sheet", "the Movement Source Sheet") and resolve real IDs at runtime from
`$PLUGIN_DATA/sheet-ids.json`, set up by the onboarding hook on the
coach's own machine.
- **Google auth** is handled entirely by `gogcli`, which is keychain-backed,
per-account OAuth on the coach's own machine. This plugin never embeds or
requests Google credentials directly.
- **Rubicon auth** for publishing is the coach's own OAuth login against the
Coach MCP Surface (`.mcp.json`, Streamable HTTP,
`https://www.rubicon.fitness/api/mcp`). The surface uses lazy
authentication — anonymous connect and tool listing are fine, and an OAuth
challenge with dynamic client registration fires only when a protected
tool (like `programming_write_dry_run` / `programming_write_publish`) is
called. No static credentials live in `.mcp.json` or anywhere else in
this repo.
- `programming_write_publish` requires the `programming:admin` scope, which
the coach gets automatically because their Rubicon account already holds
the `coach` role — no special OAuth client provisioning is needed beyond
normal login and consent.
## What's public vs. what's not
- **Public, and intentionally so:** the coaching methodology encoded in
`skills/programming-inference/SKILL.md` (how ME/DE/RE conjugate-method
concepts map onto Rubicon's programming graph, DE wave progression
conventions). This is coaching craft, not a secret.
- **Never public:** the coach's actual sheet IDs/URLs and any Google or
Rubicon credentials or tokens. These only ever exist locally, resolved at
runtime from `$PLUGIN_DATA`.
## Known uncertainties
This plugin was scaffolded against best-effort understanding of Codex
plugin conventions at authoring time. A few things are worth double-checking
against current Codex plugin docs before treating them as gospel:
- The exact `.codex-plugin/plugin.json` manifest schema (field names for
skills/hooks/mcp wiring).
- The `onInstall` hook lifecycle event name in `hooks/hooks.json` — this is
a reasonable guess for "runs on first install," not a confirmed API.
- Exact `gog` (gogcli) CLI flags for reading sheet ranges — `sheet-read`
documents the shape generically and tells the agent to check
`gog sheets --help` rather than asserting exact flags.
## License
MIT — see `LICENSE`.