Install
$ agentstack add skill-max4c-skills-cookoff ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Cookoff
Run grill-me style interrogation between Claude and Codex so the user only reviews the output instead of answering questions live. Uses the same five-dimension ambiguity rubric as max:grill-me (Goals, Acceptance, Boundaries, Alternatives, Assumptions) but with an AI playing the answerer — and in parallel mode, playing a second griller too.
The point: extract the easy 80% of a grill-me pass autonomously. Consensus defaults get baked in, real disagreements get flagged as [NEEDS MAX] — so the user's attention is spent only on the genuine judgment calls.
When to use
- User has an artifact (plan, spec draft, ticket, PRD) and wants it stress-tested without sitting through the interview
- Explicit invocation: "cookoff", "pre-grill", "have the AIs grill it", "/cookoff"
- As a pre-filter before
max:grill-me: cookoff resolves the obvious questions; follow up withmax:grill-meon only the[NEEDS MAX]items
When NOT to use
- The user wants to be interviewed themselves — use
max:grill-medirectly - There's no artifact yet (nothing to grill) — use
max:write-prdor similar to generate a draft first - The artifact is trivial (a one-line decision) — overkill
Modes
relay — iterative back-and-forth, one question at a time:
- Claude generates a grilling question, sends it to Codex via
task - Codex answers as if it were the artifact's author
- Claude evaluates: concrete enough? If vague, follows up with
task --resume-last - Loop until the ambiguity rubric is below threshold
- Good for: deep probing on a small artifact where each answer shapes the next question
parallel — two streams with swapped roles, merged:
- Stream A: Claude generates a full question set → Codex answers all in one shot (as author-proxy)
- Stream B: Codex generates a full question set → Claude answers all in one shot (as author-proxy)
- Each stream runs as a one-shot Codex call (no iterative resume) so the two streams don't race on
--resume-laststate - Merge: consensus answers become
[CONSENSUS], disagreements become[CONFLICT: ...], unique questions appear tagged with which stream caught them - Good for: broader coverage on a larger spec — two different grilling styles surface different gaps
Default: if the user doesn't specify, pick relay for short artifacts ( — grill the file at `
/cookoff relay— force relay mode/cookoff parallel— force parallel mode/cookoff --to-tickets— after grilling, decompose the spec into Dahso Agent Tickets and stop (see--to-tickets flagsection)/cookoff --to-tickets --go— same, then chain immediately todahso:go
Flags combine with modes: /cookoff relay --to-tickets --go is valid.
Before starting, confirm the artifact you're about to grill in one line ("Grilling: ") so the user can redirect if you picked wrong.
Calling Codex
Invoke Codex directly via Bash. Don't go through codex:codex-rescue — that's a one-shot forwarder designed for single rescue requests; cookoff owns its own Codex conversation.
Resolve the script path first:
The companion script lives inside the openai-codex plugin cache. The version directory changes on updates, so always resolve dynamically:
CODEX_SCRIPT=$(ls -d ~/.claude/plugins/cache/openai-codex/codex/*/scripts/codex-companion.mjs 2>/dev/null | sort -V | tail -1)
if [ -z "$CODEX_SCRIPT" ]; then
echo "ERROR: codex-companion.mjs not found. Is the openai-codex plugin installed?"
exit 1
fi
Use $CODEX_SCRIPT for all subsequent calls. If CLAUDE_PLUGIN_ROOT is set in the environment, you can use ${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs instead — but the dynamic lookup is the safer default.
Fresh call:
node "$CODEX_SCRIPT" task --fresh ""
Continue the same thread:
node "$CODEX_SCRIPT" task --resume-last ""
Rules:
- Leave
--modeland--effortunset unless the user specified them - Don't pass
--write— cookoff is a read/analyze operation, not a code-edit operation - If Codex returns an error or empty output, stop and report — don't fabricate answers
Relay mode flow
1. Load artifact
- File path → Read it
- Conversation reference ("the plan we just discussed") → extract the relevant content into a single artifact blob
- Pasted content → use as-is
2. Set Codex's role (first turn)
Fire a fresh task with this prompt structure:
You are playing the role of the author of the following artifact. Another engineer is going to grill you on it across five dimensions: Goals, Acceptance, Boundaries, Alternatives, Assumptions. Answer each question as concretely as you can, as if you had actually designed this.
Important rules:
- When you're genuinely uncertain — when the real author would need to weigh in — start your answer with "UNCERTAIN:" and explain what you'd need to know.
- When the artifact references external context you don't have access to (e.g., "use the same auth flow as the mobile app", "follow our existing deployment pipeline"), do NOT guess. Start your answer with "UNCERTAIN:" and note the external dependency.
- Brevity over filler. A sentence or two per answer is usually enough.
Artifact:
---
---
First question:
3. Iterate
For each follow-up:
- Use
--resume-lastto continue - Read Codex's answer, judge it against the rubric (is the relevant dimension now concrete?)
- If vague, push back with a sharper follow-up
- If concrete, move to the next dimension
- Track which dimensions still need work
Round budget: Cap at 10 rounds total. To prevent one dimension from starving the others, move on from any single dimension after 3 rounds of follow-up. If a dimension isn't concrete after 3 rounds, flag it [NEEDS MAX] and proceed — you're better off covering all five dimensions shallowly than drilling into one while ignoring others.
4. Exit
Use the exact exit procedure from max:grill-me:
- Judge each of Goals / Acceptance / Boundaries / Alternatives / Assumptions on the 0/0.25/0.5/0.75/1.0 rubric
- Aggregate = mean
- Default threshold: 0.3 (moderate — same as ticket mode in grill-me)
- If below threshold, exit; if above, do one more round of targeted questions on the weakest dimension, then exit regardless
If you hit the 10-round cap without clearing the threshold, exit anyway and flag the residual weak dimensions as [NEEDS MAX] in the final spec.
5. Render the grilled spec
Rewrite the original artifact with resolved decisions inline. Tag each decision:
[AGREED]— Codex gave a concrete answer Claude found reasonable on first response[PLAUSIBLE DEFAULT]— Codex answered concretely after a follow-up; reasonable but the user may want to override[NEEDS MAX]— Codex said UNCERTAIN, or Claude couldn't get to concrete after follow-up
Append the full ambiguity report (same format as max:grill-me).
Parallel mode flow
1. Load artifact (same as relay)
2. Spawn two streams
Fire two Codex calls. Note: these are "concurrent-ish" — Stream A is a single Codex call while Stream B requires a Codex call followed by a Claude answering pass. In practice Stream A often finishes first. That's fine; the merge step waits for both.
Do not try to run iterative --resume-last conversations concurrently — --resume-last resolves to "the most recent thread for this session" and two parallel iterative streams would race. Each stream is a single Codex call with all context inline.
Stream A prompt (Claude grills, Codex answers):
Claude first generates a full question set (5-10 questions covering all five dimensions). Then fires one fresh Codex task:
You are playing the role of the author of the following artifact. Answer the questions below concretely, as if you had designed this.
Important rules:
- For any question where the real author would need to weigh in, start your answer with "UNCERTAIN:" and explain what you'd need.
- When the artifact references external context you don't have (other systems, prior decisions, existing codebases), do NOT guess — mark UNCERTAIN and note the dependency.
- Keep each answer tight — a sentence or two is usually enough.
Artifact:
---
---
Questions:
1.
2.
...
Stream B prompt (Codex grills, Claude answers):
Claude fires one fresh Codex task asking for a question set:
You are reviewing the following artifact. Generate a focused set of 5-10 grilling questions across these five dimensions — Goals, Acceptance, Boundaries, Alternatives, Assumptions. Prioritize questions where two reasonable engineers would build different things if left unresolved. Output as a numbered list, one question per line, tagged with its dimension.
Artifact:
---
---
Codex returns a question list. Claude then answers each one from the perspective of the artifact's author — flagging UNCERTAIN where a real author would need to weigh in (including external context references). This answering step happens in Claude's own context, no Codex call needed.
3. Merge
Compare the two resolved-spec outputs. For each decision:
- Same concrete answer in both streams →
[CONSENSUS] - Different concrete answers in both streams →
[CONFLICT: A said X / B said Y] - Only one stream surfaced the question → include it, tag with origin (
[A-only]/[B-only]) and whether it was resolved or UNCERTAIN - UNCERTAIN in either stream →
[NEEDS MAX]
4. Present merged spec
Rewrite the artifact with all decisions tagged. Append one combined ambiguity report scored on the merged result.
Output format
Always end the response with:
- Grilled artifact — the original content with resolved decisions inline, each tagged per mode
- Ambiguity report — same format as
max:grill-me:
`` Ambiguity Report: Goals: 0.25 ⚠ one gap Acceptance: 0.1 ✓ clear Boundaries: 0.0 ✓ clear Alternatives: 0.5 ⚠ underexplored Assumptions: 0.1 ✓ clear ────────────────────────────── Aggregate: 0.19 ✓ below threshold (0.3) ``
- Diff summary — 3-5 bullets describing what got filled in vs. the original
- Next step suggestion — if any
[NEEDS MAX]items remain, suggest runningmax:grill-mescoped to those specific items; otherwise say the artifact is ready
--to-tickets flag
When --to-tickets is passed, after producing the grilled spec, decompose it into Dahso tickets so dahso:go has something to execute against. The intended pipeline is: idea → max:write-prd → max:cookoff --to-tickets → dahso:go → wake up, review the worktree, merge or delete.
Decomposition rule
Parse the grilled spec's top-level numbered sections (e.g. "1. Data model", "2. Conflict resolution") and decompose into tickets using this logic:
- Every numbered section becomes at least one ticket, regardless of tag. Wrong code in a worktree is cheap to delete; skipped work is a wasted night. Don't self-censor
[NEEDS MAX]sections — turn them into tickets with annotated defaults (see below). - Split sections that span multiple layers into separate tickets. Signals that a section should split: it mentions different directories (Swift client vs. Cloudflare Worker vs. CLI), touches different files, or contains two distinct implementation units described back-to-back.
- The success criteria / acceptance test / demo section becomes its own dedicated ticket. Title: "Write integration tests for " or "Verify end-to-end". Priority: High. The spec's pass/fail criteria become the ticket's
## Done When.
Tag handling inside the ticket body
Each ticket's body is built from the corresponding spec section plus tag-specific preamble:
[AGREED]— copy the section content into## Whatverbatim. No extra note.[PLAUSIBLE DEFAULT]— copy into## Whatverbatim, then append an## Agent Notesection: "Based on a plausible default, not explicitly confirmed by the user. If is wrong, change to ."[NEEDS MAX]— pick the most reasonable option yourself, write the ticket body around that choice, and append an## Agent Notesection:
`` Agent chose over because . This was unresolved in the original spec ([NEEDS MAX]). Review and revert/adjust if the other option was preferred. ``
Do NOT skip [NEEDS MAX] sections. Ship a default and flag it — that's the whole point of this flag.
Priority assignment
- Infrastructure / data-model / schema / migration tickets → High (everything else depends on them)
- Integration test / acceptance-criteria tickets → High (should run early to validate)
- Core feature tickets → Medium
- UX / banners / error messages / nice-to-have polish → Low
Database setup
Reuse the cache owned by dahso:flow at ~/.dahso/flow-cache.json:
{ "agent_projects": "", "agent_tickets": "" }
If the cache exists, read it. If not, or if a cached ID fails:
dahso db list
Find Agent Projects and Agent Tickets, then mkdir -p ~/.dahso && .
If the dahso CLI isn't on PATH, fall back to swift run DahsoCLI from the repo root. The argument syntax is identical.
Create the project
Derive a short project name from the grilled spec's Goal / opening section. Keep it under 60 characters.
dahso create "Agent Projects" \
--set "Name=" \
--set "Status=Active" \
--body-file -
Source: cookoff (grilled )
EOF
Capture the returned row_id — every ticket below references it via the Project relation.
Create each ticket
For each decomposed ticket:
cat " \
--set "Status=To Do" \
--set "Project=" \
--set "Priority=" \
--set "Files=" \
--set "Source=cookoff" \
--body-file -
## What
## Done When
## Agent Note
SPEC
Save every returned row_id. Ticket titles must be imperative ("Add workspacemembers table", not "workspacemembers table") and under 80 characters.
Detect file overlaps
After all tickets are created, scan their Files fields. For each pair of tickets that shares at least one file, populate both Linked fields:
# Pair sharing files
dahso update "Agent Tickets" --set "Linked="
dahso update "Agent Tickets" --set "Linked="
# Ticket A shares files with both B and C
dahso update "Agent Tickets" --set "Linked=,"
Linked tickets must be committed together — they touch the same files and partial commits leave the tree inconsistent. dahso:go uses this field to decide lane grouping.
Print summary
After creation, print a scannable summary:
Created N tickets under project "" (row ):
1. [High] Add workspace_members D1 schema — shared-worker/schema.sql
2. [High] Implement R2 client in Dahso — Sources/DahsoCore/Sync/*.swift linked to #3
3. [Medium] Wire sync to FSEvents watcher — Sources/DahsoCore/Sync/*.swift, Sources/Dahso/Services/WorkspaceWatcher.swift linked to #2
4. [Low] Offline banner UI — Sources/Dahso/Views/Components/SyncStatusBanner.swift
5. [High] Integration test: create-update-delete across two machines — Tests/SharedWorkspaceTests/*.swift
Of these, M are based on [NEEDS MAX] items (agent picked defaults):
- #2: chose opaque bearer tokens over JWT because the spec's `workspace_members` table already carries `token_hash`. Flip to JWT if revocation needs to be stateless.
Review in Dahso before `/go`, or proceed directly.
--go follow-through
If invoked as --to-tickets --go, invoke dahso:go immediately after printing the summary. No review pause. The /go run logs its own progress.
If invoked as just --to-tickets (no --go), stop here so the user can review in the Dahso app first.
Do NOT invoke dahso:go unless --go was explicitly passed alongside --to-tickets.
Exit discipline
- The user can override at any time ("enough", "ship it", "good enough") — exit immediately, print the report anyway so the override is informed
- If Codex errors out mid-stream, stop and report the error — don't fall back to doing the g
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: max4c
- Source: max4c/skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.