Skip to content

Commit ff8747b

Browse files
Polish: CI workflows + 3 Codex lints + Codex-tailored docs + logo
CI workflows (vendored from cursor-lua-agent-builder, adapted): - .github/workflows/ci.yml: matrix [macos-14, ubuntu-22.04, windows-2022] × [node 18, 20], plus standalone mcp build/test job - .github/workflows/release-prod.yml: tag prefix `codex-v` (vs Cursor's `cursor-v` and CC's `v`); skip-not-fail when tag exists; tarball name corrected to codex-lua-plugin-<v>.tar.gz Three new Codex-specific lints: - lint-codex-manifest.mjs: validates .codex-plugin/plugin.json against Codex's documented schema (required: name + version + description; name kebab-case; semver version; only known optional fields). - lint-codex-mcp-config.mjs: validates .mcp.json's source tree references resolve (mirrors Cursor port pattern — checks source not built artifact, since dist/ is gitignored). - lint-codex-no-claude-root.mjs: catches stray ${CLAUDE_PLUGIN_ROOT} OR ${CURSOR_PLUGIN_ROOT} refs that didn't get converted (Codex auto-resolves bundled-asset paths from the plugin root, no host variable needed). Docs rewritten for Codex (were vendored Cursor content): - docs/USER_GUIDE.md: install via `codex plugin marketplace add` + `codex plugin install`; troubleshooting tailored to Codex; subagent section explains TOML format + natural-language dispatch. - docs/TESTERS.md: 5-min setup with Codex-CLI prereq, sanity check aimed at tester audience, "what we're watching for" section highlights Codex-specific seams (TOML agent parsing, plugin install success, hook event coverage). - SECURITY.md: scope updated for Codex paths; safety-contract table correct; hook safety model section explains Codex's protocol (Claude-Code-shaped, exit 2 + JSON envelope) + the matcher self- filtering proactive defense. Logo: 400×400 official Lua logo at repo root for marketplace listings. All 12 lints pass, 248/248 tests pass locally. Ready to ship to testers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 24fae87 commit ff8747b

9 files changed

Lines changed: 307 additions & 124 deletions

File tree

.github/workflows/ci.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@ on:
66
pull_request:
77
branches: [main, staging]
88

9-
# Single-plugin repo (no plugins/ subdir, unlike claude-code-lua-plugin which is
10-
# a marketplace catalog). Working directory is the repo root.
9+
# Single-plugin repo (no plugins/ subdir, unlike claude-code-lua-plugin which
10+
# is a marketplace catalog). Working directory is the repo root.
1111
#
12-
# Cross-platform matrix because the plugin must work on macOS, Linux, and
13-
# Windows — the same coverage as the Claude Code plugin (Node ESM hooks,
14-
# AbortSignal.timeout, path handling all need verification per cell).
12+
# Cross-platform matrix: the plugin's hook scripts and MCP server must work
13+
# on macOS, Linux, and Windows — same coverage discipline as the Claude Code
14+
# and Cursor ports (Node ESM hooks, AbortSignal.timeout, path handling all
15+
# need verification per cell). Codex CLI itself is not exercised in CI;
16+
# the install script's preflight checks for `codex` on PATH at user-install
17+
# time, but CI tests the bundled hooks/MCP/lints in isolation.
1518

1619
jobs:
1720
plugin:

.github/workflows/release-prod.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ on:
88
# package.json version was bumped. If the tag already exists (no version
99
# bump), the release step is skipped — lints + tests still run.
1010
#
11-
# Tag prefix is `cursor-v` (claude-code-lua-plugin uses `v`) to keep the two
12-
# repos' tags from colliding when cross-referenced.
11+
# Tag prefix is `codex-v` (Cursor port uses `cursor-v`, claude-code-lua-plugin
12+
# uses `v`) to keep the four repos' tags from colliding when cross-referenced.
1313

1414
permissions:
1515
contents: write
@@ -61,7 +61,7 @@ jobs:
6161
echo "::error::Production release requires a stable version in package.json (no -beta/-rc/-alpha suffix). Got: ${VERSION}"
6262
exit 1
6363
fi
64-
echo "tag=cursor-v${VERSION}" >> "$GITHUB_OUTPUT"
64+
echo "tag=codex-v${VERSION}" >> "$GITHUB_OUTPUT"
6565
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
6666
echo "Production version: ${VERSION}"
6767
@@ -79,7 +79,7 @@ jobs:
7979
if: steps.tag_check.outputs.skip != 'true'
8080
run: |
8181
node scripts/pack.mjs
82-
TARBALL="cursor-lua-agent-builder-${{ steps.version.outputs.version }}.tar.gz"
82+
TARBALL="codex-lua-plugin-${{ steps.version.outputs.version }}.tar.gz"
8383
ls -lh "${TARBALL}"
8484
echo "TARBALL=${TARBALL}" >> "$GITHUB_ENV"
8585

SECURITY.md

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,28 @@ We aim to acknowledge within 2 business days and ship a fix within 30 days for h
1010

1111
This plugin's surface includes:
1212

13-
- **Skills** (`skills/<name>/SKILL.md`) — Markdown prompts that Cursor loads as `/lua-*` slash commands. Symlinked into `~/.cursor/skills-cursor/` by `scripts/install.mjs`.
14-
- **Subagents** (`agents/*.md`) — referenced by skills; specialised assistants for architect/build/debug/deploy/QA flows.
15-
- **Hooks** (`hooks/*.mjs`) — run as Node subprocesses on `sessionStart`, `beforeSubmitPrompt`, `beforeShellExecution`, `afterShellExecution` events. Registered in `~/.cursor/hooks.json` by the install script.
16-
- **MCP server** (`mcp/lua-platform/dist/server.js`) — a stdio MCP server exposing 5 read-only tools. Talks to `https://api.heylua.ai` over HTTPS using the user's API key. Registered in `~/.cursor/mcp.json`.
13+
- **Skills** (`skills/<name>/SKILL.md`) — Markdown prompts that Codex loads as `/lua-*` slash commands. Bundled via the plugin manifest at `.codex-plugin/plugin.json`.
14+
- **Subagents** (`agents/*.toml`) — Codex TOML-format subagent definitions with `name`, `description`, `developer_instructions`. Bundled with the plugin.
15+
- **Hooks** (`hooks/*.mjs`) — run as Node subprocesses on `SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse` events. Registered in `hooks/hooks.json` (Claude-Code-shaped schema; Codex consumes it natively).
16+
- **MCP server** (`mcp/lua-platform/dist/server.js`) — a stdio MCP server exposing 5 read-only tools. Talks to `https://api.heylua.ai` over HTTPS using the user's API key. Registered in `.mcp.json`.
1717
- **Rules** (`rules/*.mdc`) — knowledge files attached to the architect agent's context via `@-mention`.
18-
- **Install script** (`scripts/install.mjs`) — modifies `~/.cursor/mcp.json` and `~/.cursor/hooks.json` (always with backup). Runs only when explicitly invoked by the user.
18+
- **Install script** (`scripts/install.mjs`) — runs `codex plugin marketplace add` + `codex plugin install`. Does not modify any user files outside Codex's plugin cache (`~/.codex/plugins/cache/`).
1919

2020
In scope for security reports:
2121

2222
- Credential exposure (API keys leaking into transcripts, logs, environment, or external systems)
2323
- Safety-gate bypasses (deploys or destructive operations succeeding without the documented confirmation)
2424
- Hook payload injection (a maliciously-shaped command triggering unintended hook behavior)
2525
- MCP server auth bypass
26-
- Install script writing outside `~/.cursor/` or executing without explicit user invocation
27-
- Symlink-target manipulation (an installed skill resolving to a path outside the cloned plugin)
26+
- Symlink-target manipulation (a bundled component resolving to a path outside the cloned plugin)
2827

2928
Out of scope:
3029

31-
- Bugs in `lua-cli` itself (report to the lua-cli repo or via security@heylua.ai with `[lua-cli]` in the subject)
30+
- Bugs in `lua-cli` itself (report to security@heylua.ai with `[lua-cli]` in the subject)
3231
- Bugs in `lua-api` (report to security@heylua.ai with `[lua-api]` in the subject)
32+
- Bugs in Codex CLI itself (report to OpenAI)
3333
- Issues in user-installed third-party MCP servers
34-
- Social-engineering / phishing of an Lua API key from a user
34+
- Social-engineering / phishing of a Lua API key from a user
3535

3636
## Safety-critical contracts
3737

@@ -41,25 +41,26 @@ The plugin enforces several safety contracts. Bypasses count as security issues.
4141
|---|---|
4242
| **§3.3 deploy gate**: bare `lua deploy` is denied | `hooks/before-shell-execution.mjs` (umbrella) + `hooks/confirm-deploy.mjs` (dedicated) |
4343
| **§3.3 auto-deploy block**: `--auto-deploy` is denied | `hooks/before-shell-execution.mjs` + `hooks/block-auto-deploy.mjs` |
44-
| **Credential isolation**: API key never enters chat transcript | `hooks/before-shell-execution.mjs` denies `lua auth key*` invocations + `commands/lua-doctor.md` Step 4 uses an authenticated metadata probe (`lua agents --json --ci`), not a key-printing command |
45-
| **§3.7 single-permission contract**: each skill asks at most one prompt per invocation | Convention enforced in skill bodies; not yet machine-checked in the Cursor port (was lint-checked in the Claude Code plugin via `scripts/lint-single-permission.mjs`) |
44+
| **Credential isolation**: API key never enters chat transcript | `hooks/before-shell-execution.mjs` denies `lua auth key*` invocations + `skills/lua-doctor/SKILL.md` Step 4 uses an authenticated metadata probe (`lua agents --json --ci`), not a key-printing command |
45+
| **§3.7 single-permission contract**: each skill asks at most one prompt per invocation | Convention enforced in skill bodies |
4646

4747
If you find a way to bypass any of these without an explicit user prompt, please report.
4848

49-
### Hook safety model under Cursor
49+
### Hook safety model under Codex
5050

51-
Cursor sends `beforeShellExecution` hooks structured stdin JSON `{command, cwd, ...}` and accepts either an exit code (2 = block) or a JSON return `{permission: "deny", user_message, agent_message}`. The plugin's hooks self-filter on `command` content rather than relying on Cursor's `matcher` field — a bug fix landed in `a85cff7` after the matcher proved unreliable in the wild and caused every shell command to be denied.
51+
Codex sends `PreToolUse` hooks structured stdin JSON `{tool_input: {command, ...}, tool_name, hook_event_name, ...}` (the same shape as Claude Code) and accepts either an exit code (2 = block) or a JSON envelope `{hookSpecificOutput: {hookEventName, permissionDecision}}`. The plugin's hooks self-filter on `command` content rather than relying on Codex's `matcher` field — defense-in-depth in case Codex's matcher behaviour ever drifts (a bug-class we hit on the Cursor port; same mitigation applied here proactively).
5252

53-
The runtime adapter (`lib/hook-runtime.mjs`) detects whether it's running under Claude Code or Cursor (via `CURSOR_TRACE_ID` env or input shape) and emits the host-appropriate output protocol. The same hook scripts run unchanged on either host.
53+
The runtime adapter (`lib/hook-runtime.mjs`) detects whether it's running under Claude Code, Cursor, or Codex (via env vars or input shape) and emits the host-appropriate output protocol. The same hook scripts run unchanged on all three hosts.
5454

5555
## Audit history
5656

57-
This plugin is a port of [`claude-code-lua-plugin`](https://github.com/lua-ai-global/claude-code-lua-plugin), which underwent 13 iterations of structured audit (commits prefixed with `iteration-`) before public release, fixing 78 documented bugs across the plugin / hook / MCP / knowledge-file surfaces. See the iteration-history comments in each lint script (`scripts/lint-*.mjs`) for the rationale behind each structural guard.
57+
This plugin is the third in a family ported from [`claude-code-lua-plugin`](https://github.com/lua-ai-global/claude-code-lua-plugin), which underwent 13 iterations of structured audit (commits prefixed with `iteration-`) before public release, fixing 78 documented bugs across the plugin / hook / MCP / knowledge-file surfaces. See the iteration-history comments in each lint script (`scripts/lint-*.mjs`) for the rationale behind each structural guard.
5858

59-
The Cursor port adds:
59+
The Codex port adds:
6060

6161
- A new `before-shell-execution.mjs` umbrella hook covering all three §3.3 deny patterns
62-
- Cursor-runtime detection + input/output normalisation in `lib/hook-runtime.mjs`
63-
- Cursor-specific lints: `lint-cursor-manifest`, `lint-cursor-mcp-config`, `lint-cursor-no-claude-root`
64-
- Test coverage for the Cursor branches (248/248 tests passing as of v1.0.0)
65-
- A regression-test bundle covering the `confirm-deploy.mjs` matcher-leak bug fix in `a85cff7`
62+
- Codex-runtime detection in `lib/hook-runtime.mjs` (falls through to Claude Code's protocol since Codex's hook input/output match)
63+
- Codex-specific lints: `lint-codex-manifest`, `lint-codex-mcp-config`, `lint-codex-no-claude-root`
64+
- Marketplace-based install via `codex plugin marketplace add` + `codex plugin install` (no symlink dance like Cursor needed)
65+
- Conversion of subagent files from Markdown frontmatter to Codex's TOML schema
66+
- 248/248 tests passing as of v1.0.0

0 commit comments

Comments
 (0)