castmate

$npx mdskill add coreyhaines31/makerskills/castmate

You are the host agent. Castmates are other AI coding CLIs installed on this machine. A small script, `scripts/castmate.py` in this skill's folder, runs them. You decide who gets cast, write the prompt, read what comes back, and tell the user what it means.

SKILL.md

.github/skills/castmateView on GitHub ↗
---
name: castmate
description: "When you want to pull in the right AI model for the right job: hand a task to another agent CLI (Codex, Claude, Gemini, Amp, OpenCode, Cursor, Kiro, Antigravity), or send one prompt to several at once for independent opinions, then synthesize. Delegate mode gives one castmate the job, optionally with write access ('have codex write the migration'). Fan-out mode runs read-only reviews in parallel. Rounds mode lets castmates build on and challenge each other's findings. Calls the official CLIs you already have installed and logged in (Gemini CLI needs an API key on personal accounts); no MCP. Triggers on '/castmate,' 'ask codex,' 'have gemini do this,' 'get a second opinion,' 'what would other models say,' 'fan this out,' 'cross-check this with another model,' 'delegate this to codex.' Advisor personas for founder questions go to maker-council. Personal models, casting rules, and run outputs live in ~/.config/makerskills/castmate/."
metadata:
  version: 0.1.0
---

# /castmate — the right model for the right job

You are the host agent. Castmates are other AI coding CLIs installed on this machine. A small script, `scripts/castmate.py` in this skill's folder, runs them. You decide who gets cast, write the prompt, read what comes back, and tell the user what it means.

Adapted from [counselors](https://github.com/aarondfrancis/counselors) by Aaron Francis (MIT). Discovery, prompt writing, and synthesis moved from code into this workflow, and the model list moved into config so it doesn't go stale.

```bash
python3 <skill-dir>/scripts/castmate.py list            # castmates, groups, install + read-only status
python3 <skill-dir>/scripts/castmate.py test codex fable # each must reply "OK"
python3 <skill-dir>/scripts/castmate.py run -c codex-sol-high,fable-high -f prompt.md --json
```

`<skill-dir>` is this skill's install folder. In Claude Code it is the skill's base directory.

## First run

**Before the first cast in a session, run `castmate.py test` on the castmates you plan to use.** It takes 5–15 seconds. `list` only shows that a CLI is installed, not that it's logged in or that the account has the model. If nothing is installed, or a test fails, set the user up first. **`references/cli-setup.md` is the setup guide.** Walk through it rather than reciting it:

1. Ask which agent CLIs they already use. One logged-in CLI is enough to start. Suggest Codex if they have none: it's the only one that confines `--write` to `--cwd`.
2. Give the install and login commands for their pick. Login is interactive, so the user runs it in their own terminal (in Claude Code they can type `! codex login` in the prompt). Then restart the agent if PATH or the shell profile changed.
3. Run `castmate.py test <castmate>`. Use `gemini-flash` for a first Gemini check, since not every key has `gemini-argon`. On failure, relay the `hint:` line it prints and the matching guide section.
4. **Never ask the user to paste an API key into chat.** For Gemini CLI, have them put `GEMINI_API_KEY` in their shell profile and restart the agent, or enter it in `gemini` directly. If they already tried Google sign-in, the key alone won't work until the saved `oauth-personal` auth type is switched. Use the one-liner in the guide's Gemini step 2. If a key does get pasted, say so, tell them to rotate it, and point to the guide's rotation steps.

Mention the gotchas that apply before they hit them. Gemini CLI no longer accepts Google sign-in on personal accounts. Antigravity's installer edits shell profiles, and its read-only mode is best-effort.

## Config (user state, outside the install folder)

`CONFIG=${MAKERSKILLS_CONFIG:-$HOME/.config/makerskills}/castmate`

- `$CONFIG/config.json` uses the same shape as `references/tools.json` and is merged on top of it. Add a castmate alias, a group, or a new CLI adapter here.
- `$CONFIG/casting.local.md` holds the user's own "use X for Y" rules. Read it before `references/casting.md`.
- `$CONFIG/runs/` is the default output folder, one subfolder per run.

**A new model needs no config at all.** `-c codex:gpt-5.7@high` or `-c claude:some-new-model` passes the model ID straight to the CLI. Offer to save an alias in `config.json` once it proves useful:

```json
{"castmates": {"sol7": {"tool": "codex", "model": "gpt-5.7", "effort": "high", "note": "GPT-5.7, high"}},
 "groups": {"review": ["fable-high", "sol7"]}}
```

## Step 1 — Pick the mode

| Mode | Castmates | Access | Use when |
|---|---|---|---|
| **Delegate** | 1 | read-only answer, or `--write` | A job to hand off: "have codex write the migration," "get haiku to summarize these logs" |
| **Fan-out** | 2–4 | read-only | Independent second opinions on a plan, diff, or decision |
| **Rounds** | 2–4, 2–4 rounds | read-only | Broad hunts (bugs, security, performance) where later rounds build on earlier ones |

If the request is vague, default to fan-out with two castmates. A named castmate plus a task ("ask codex to…") means delegate.

## Step 2 — Cast

1. Run `castmate.py list`. Show the user the castmates that matter for this job, not the whole table.
2. Read `$CONFIG/casting.local.md` (if present), then `references/casting.md`. Recommend a cast with a one-line reason for each.
3. Flag `unverified` adapters and `best-effort` read-only levels before dispatching. If an adapter has never been tested here, run `castmate.py test <name>` first.
   - **`enforced`** means the CLI's own sandbox or permission settings stop file writes, shell commands, MCP tools, and repo-level config such as hooks. Claude, Codex, and Gemini have been tested against a repo that plants hooks and MCP servers.
   - **`best-effort`** means the castmate is asked to stay read-only, but repo or user config can still give it more access. **Don't cast `best-effort` castmates on code the user didn't write** (a cloned repo, a contributor's PR) without saying so first.
4. **Confirm the exact list before dispatch:** "Casting: **codex-sol-high**, **fable-high**, read-only. OK?" Always confirm `--write` runs, and name the working directory.

Groups expand to their members, so show the expanded list. If the user names a group that doesn't exist, say so and don't guess.

## Step 3 — Write the prompt

Use `references/prompt-template.md`: the **Delegate** template for delegate mode, and the **Review** template for fan-out and rounds. For a focused hunt, paste a preset from `references/presets/` into the Instructions section.

- Gather context first: files named in the request, `git status` and `git diff`, and up to 5 related files found by search. **Reference files by path. Don't paste their contents.** Castmates read files themselves.
- **Paste the diff into the prompt** when the review is about changes. Claude castmates have no shell in read-only mode, so they can't run git.
- In a blind review, leave out your own conclusion. A castmate given your hypothesis tends to confirm it.
- Save the prompt to a temporary file, or pipe it with `-f -`.

## Step 4 — Dispatch

```bash
python3 <skill-dir>/scripts/castmate.py run -c <castmates> -f <prompt-file> [--write] [--cwd <repo>] [--timeout 540] --json
```

- Castmates can take 2–15 minutes each. Tell the user the ETA, then run the command in the background if the host supports it, so you can keep talking while it runs. The script prints a `still running: … (pid, elapsed)` line every 30 seconds on stderr; pass those along when the user asks or a run goes long.
- If a castmate goes well past its ETA, check the PID (`ps -p <pid>`) and tell the user. Don't wait silently.
- `--write` takes exactly one castmate. Before running it, check that the working tree is committed or stashed, so the castmate's changes form a clean diff.
  - **Only Codex limits writes to `--cwd`**, using its workspace sandbox. Claude, Gemini, Antigravity, and the others run with the user's full file access and are only *asked* to stay in `--cwd`. Say this when you confirm a non-Codex write run.
- Exit codes:
  - **0:** at least one castmate succeeded.
  - **1:** all castmates failed.
  - **2:** setup error, such as an unknown castmate, a missing binary, a refused `--write`, or a bad path.
  - **130 / 143:** interrupted by Ctrl+C or SIGTERM. Running castmates are stopped, queued ones never start, and `run.json` marks them `aborted` with their partial output.
- `--out` must be a new or empty folder. A read-only run refuses an `--out` inside `--cwd`, so it can't write into the tree it reviews. Without `--out`, each run gets a unique folder under `$CONFIG/runs/`.

## Step 5 — Read results

`run.json` in the output folder lists each castmate's `status`, `durationS`, `words`, `outputFile`, `stderrFile`, and the exact `command`.

- `success`: read `outputFile`.
- `timeout`: `outputFile` holds partial output. Use it, labeled as partial.
- `error` or `empty`: if the report has a `hint`, relay it first; it names the fix and the `cli-setup.md` section. Otherwise read `stderrFile`. Common causes are an expired login, a model the account can't use, or a flag a newer CLI version renamed. Report it and carry on with the rest. Antigravity returns `empty` whenever headless mode denies one of its tool calls, even after a long run, and drops the whole answer. If that happens, rerun with a narrower prompt or cast someone else.

## Step 6 — Present

**Delegate.** Review the castmate's work before calling it done. For `--write`, read `git diff`, run the project's tests and lint, and report what changed, what passed, and anything that looks off. You are accountable for code you hand back, whoever wrote it. For a read-only answer, relay it, and correct anything you can check that is wrong.

**Fan-out and rounds.** Synthesize; don't just concatenate:

```markdown
## Castmate review: [topic]
**Cast:** codex-sol-high, fable-high (read-only) · [N] succeeded, [N] failed
**Agree on:** [the key points castmates reached independently]
**Disagree on:** [each position and its reasoning]
**Risks flagged:** [anything one castmate raised that others missed]
**Blind spots:** [what no castmate covered that seems important]
**Recommendation:** [your call, weighing their evidence instead of counting votes]
Reports: [output folder]
```

Then offer the top 2–3 actions. If the user wants to act, plan before editing.

## Rounds mode

The host runs the rounds itself. Each round is one `castmate.py run` call into its own new folder (`--out <run>/round-N`, outside the reviewed repo).

1. Round 1: the base prompt.
2. Round N: the base prompt plus the **Round 2+ addendum** from `references/prompt-template.md`, with the prior outputs inlined (the most recent 8, about 1,500 words each).
3. Stop when you hit the preset's default round count or the user's limit, when time runs out, or when a round adds nothing beyond confirmed or duplicate labels. That last check is a judgment call: read the new findings rather than comparing word counts.
4. Write a final synthesis across all rounds in the Step 6 format, marking which findings survived challenge.

Each round costs as much as a full fan-out. State the expected total (rounds × castmates × minutes) before starting.

## Learning the cast

When a castmate is notably good or bad at a kind of job, offer to append a dated line to `$CONFIG/casting.local.md`. Ask before writing. That file is how casting improves over time.

## Adding an adapter

A CLI that isn't listed can be added in `$CONFIG/config.json` with no code change. Copy a similar entry from `references/tools.json`. Its fields:

- `binary`, `args` (before the mode args), and `argsAfter` (last).
- `prompt`: `stdin`, or `arg` together with `{prompt}` in `argsAfter`.
- `model` and `effort` flag templates.
- `readOnly`, with a `level` of `enforced` or `best-effort`, plus `args` and/or `env`. Claim `enforced` only after a planted repo hook and MCP server fail to run. Overrides in `config.json` merge key by key, so `{"readOnly": {"env": {...}}}` keeps the shipped args.
- `write` args.
- `output: last_message` with `{last_message}`, for CLIs that write their final answer to a file.

Leave `"verified": false` until `castmate.py test` passes.

## Errors

| Symptom | Do |
|---|---|
| `not found on PATH` | Walk through that CLI's section of `references/cli-setup.md`, or suggest another castmate |
| Test fails with an auth message | Relay the `hint:`. For Claude, Codex, or Antigravity, the user logs in again in their own terminal. For Gemini CLI, check the API key: Google sign-in won't work on personal accounts |
| Gemini says "no longer supported for Gemini Code Assist for individuals" | Gemini CLI needs an API key on personal accounts since 2026-06. Follow `references/cli-setup.md#gemini-cli`, or cast `antigravity` |
| Model rejected | Run `list` to find a valid alias, or ask which model their account has |
| Every castmate fails | Show the first lines of each `stderrFile`, then run `castmate.py test` on each |

More from coreyhaines31/makerskills

SkillDescription
business-brainstormWhen you want to pressure-test a potential new business, product, or side project against the serial-founder filter. Not \"marketing ideas for a product\" (that's marketing-skills:marketing-ideas) — this is \"should this business exist + can you win it.\" Runs the idea through a structured framework (problem, audience, wedge, monetization, moat, portfolio fit, distribution, energy fit, opportunity cost), checks domain availability via /domain, optionally triggers /deep-research for market validation, and outputs a viability brief: build / sleep on it / pass. Archives every idea to ~/.config/makerskills/business-brainstorm/archive/ so past work is searchable. Triggers on \"/business-brainstorm,\" \"/brainstorm,\" \"new business idea,\" \"should I build X,\" \"pressure test this idea,\" \"validate this idea,\" \"is X a good business,\" \"what about a [type] for [audience].\"
company-brainYour team's shared, AI-ready knowledge base — people, companies, meetings, SOPs, and decisions structured so an agent can answer on your team's behalf. Team-scope sibling to second-brain — personal notes go there, not here. Modes — capture, compile (wiki pages + INDEX.md), query (trust-weighted, saved to outputs/), review (verify / deprecate / supersede stale captures), lint, connect, search. Structured raw dirs (people/, companies/, meetings/, sops/, decisions/, customer-language/, sales-objections/). Every capture stamps author, timestamp, and trust status. Optional sync from call transcripts, Slack/email exports, CRM. Vault at ${COMPANY_BRAIN_VAULT:-$HOME/Documents/CompanyBrain}/. Triggers on "/company-brain," "/cb," "capture this into the team brain," "log this meeting," "save this SOP," "compile the company wiki," "query the team brain," "what does the team know about X," "review the company brain," "lint the company brain," "who's the internal expert on X."
company-cfoMonthly CFO workflow for a company or agency — pull raw data from bank + payment processor + payroll + expense management, categorize and reconcile, compute end-of-month cash via transaction-sum method, update a scenario projector for forward forecasting, write the monthly snapshot report, surface decisions to leadership. Modes — monthly (default; the standing report), weekly (thin cash pulse), scenario (ad-hoc modeling in the projector), pickup (resume where the prior run left off). Anonymized team-scope sibling to personal-cfo (which handles personal household finances). Composes with company-brain (report gets stored + wiki-indexed there), toolify (wire company-specific data sources), loopify (schedule the monthly + weekly runs). Triggers on "/company-cfo," "/cfo," "monthly cash report," "do the CFO snapshot," "CFO monthly," "let's run CFO," "cash projection," "runway forecast," "monthly financials," "cash pulse."
decideWhen you have a decision to make and want a structured workflow that picks the load-bearing questions, walks through them, reaches a call (or "wait"), and archives the rationale for future reference. Based on the 37signals Guide to Making Decisions (38 questions) plus house additions like Q39 opportunity cost ("what does saying yes displace?"). Triages to 6–8 relevant questions per decision instead of forcing the full set. Archives every decision to ~/.config/makerskills/decide/archive/ with a revisit date so you can check later whether the call was right. Triggers on "/decide," "help me decide," "should I [X]," "I need to make a decision about," "stuck on a decision," "deciding between," "go/no-go on," "what should I do about." This is both the decision-making workflow AND the decision log — making the decision is the act of logging it.
deep-researchWhen you want multi-source, multi-step research on a topic — competitor research before a sales call, market research for a new business idea, positioning angles, due diligence on a partnership or podcast guest, tech decision research (which DB, which auth), or any \"I need to actually understand X.\" Combines web search, URL fetch, agent-browser, last30days (Reddit/X/YouTube/HN/web recency), memory, and Notion. Outputs a structured brief with citations, contradictions, gaps, and recommended next steps. Archives every research run to ~/.config/makerskills/deep-research/archive/ so past work is searchable. Triggers on \"/deep-research,\" \"research X,\" \"investigate X,\" \"do a deep dive on X,\" \"look into X,\" \"what's actually happening with X,\" \"due diligence on X,\" \"validate this market.\" Differs from a one-shot web search: this is multi-pass with verification. Not for standing monitoring (radar) or pulling one post or video (social-fetch, watch-video).
domainWhen you want to brainstorm and check available .com domains for a new project — brand naming, aftermarket pricing (HugeDomains / Afternic / Sedo / Dan), USPTO trademark screening, and social handle availability. Built on Laura Roeder's \"work backwards from availability\" method. Combines Vercel CLI, whois, Domainr, Namecheap, and agent-browser, each for what it reliably does. Workflow: budget → brainstorm → availability check → whois cross-check → price → aftermarket sweep (plus liveness probe and drop-watch) → bucket → negotiate → trademark + socials → buy. Triggers on \"/domain,\" \"find a domain,\" \"check domain availability,\" \"brainstorm a domain,\" \"what .com is available for X,\" \"domain hunt,\" \"name my project,\" \"is X.com available,\" \"aftermarket price on X.com,\" \"trademark check for X.\"
ingestWhen you paste raw human input — a call transcript (Grain, Zoom, Granola, Fathom), a text or email from a client/partner/friend, a voice-memo dump, or meeting notes — and want it converted into structured work. Extracts decisions, action items (yours vs theirs), bugs/feature requests, and facts worth keeping; files GitHub issues in the right repo, captures to the second-brain vault, and drafts (never sends) the reply. Triggers on "/ingest", "ingest this", "here's my call with X," "here's the transcript," "this is from [person]," "[person] asked me this," "from [person]:", a pasted transcript with speaker labels, or a forwarded client message that clearly expects processing. Person→project routing lives in a private config; unknown senders get asked about once, then remembered.
jab-hookGary Vaynerchuk's jab-jab-jab-right-hook framework applied to a personal portfolio rotation on X and LinkedIn. Jabs = build-in-public + educational (value). Hooks = promo (the ask). Each property in the user's configured portfolio (see `~/.config/makerskills/jab-hook/properties.yaml`) gets a hook at least once every ~3 weeks; jabs fill the rest. Drafts go into the user's Typefully workspace via MCP. Modes — plan (7-day plan), pick-next (single post), audit (coverage report), draft (specific post). Triggers on "/jab-hook," "what should I post," "plan my socials," "next promo," "next jab," "next hook," "social rotation," "promote [property]," "BIP post," "audit my socials," "what haven't I posted about."
loopifyWhen you want to set up an agent loop, cron-scheduled task, or recurring workflow that runs autonomously. Judgment layer on top of Claude Code's ScheduleWakeup, CronCreate, and /loop — or, on other hosts, cron/GitHub Actions plus a headless agent CLI. Picks dynamic pacing, fixed cron, or a one-shot loop; designs idempotent loop bodies; sets bail-out conditions so loops don't run forever. Examples — weekly review pulse, daily brief, hourly metric monitor, periodic vault compile, upstream-check for an adapted skill. Triggers on "/loopify," "set up a loop," "schedule this task," "run this daily," "run this weekly," "cron this," "make this recurring," "automate this on a schedule," "keep this running until X." Part of the -ify trifecta (skillify / toolify / loopify). NOT for authoring a new skill — that's skillify. NOT for adding a tool/integration — that's toolify.
maker-councilWhen you want multiple expert perspectives on a founder/operator question — a simulated board of advisors (Jason Fried, Elon Musk, Jeff Bezos, Jensen Huang, Bob Iger, Paul Graham, Naval Ravikant, Sara Blakely, Jason Cohen). Bring a real decision — \"should I raise prices?\", \"hire my first employee?\", \"raise or bootstrap?\", \"kill this project?\" — and the council weighs in through documented frameworks, surfaces disagreements, and synthesizes a recommendation. Also use for 'maker council,' 'board of advisors,' 'what would Bezos do,' 'what would Jason Fried say,' 'channel Naval,' 'ask the council,' or how a famous founder would approach a problem. Optional live-research pass via deep-research / watch-video / last30days. Marketing questions go to marketing-skills' marketing-council. Archives to ~/.config/makerskills/maker-council/archive/. To commit to a direction, hand off to decide.