Skip to content
Development
Command

/cross-research

Two-phase multi-model research. Phase A fans codex+gemini in parallel (benchmarks + citations angles); Phase B synthesises via fresh Claude session. Usage: /cross-research [--with <id> | list | compare] <target>

From plugin
ijfw
20522 skills37 agents22 commands1 MCP
Install
$ npx -y skills add FerroxLabs/ijfw --agent claude-code

How it fires

How this command gets triggered: by you, by Claude, or both.

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/cross-research

Context preview

What this command does when you run it.

Two-phase multi-model research. Phase A fans codex+gemini in parallel (benchmarks + citations angles); Phase B synthesises via fresh Claude session. Usage: /cross-research [--with <id> | list | compare] <target>

Command definition

cross-research.md
description: "Two-phase multi-model research. Phase A fans codex+gemini in parallel (benchmarks + citations angles); Phase B synthesises via fresh Claude session. Usage: /cross-research [--with <id> | list | compare] <target>"
allowed-tools: ["Read", "Write", "Bash", "Grep"]

Deep-research triangulation from multiple agents. Solves "a single model's training data is a single lens." Parallel fan-out collects independent claim sets, then a synthesis pass merges them into a consensus/contested/unique matrix with open questions surfaced. All three requests, responses, and the merged output archive automatically.

Subcommands

| Form | Behavior | |------|----------| | `/cross-research` | **Zero-arg auto-pick.** Detect target from git state (staged → unstaged → last commit). Pick default roster (Codex=benchmarks, Gemini=citations). Generate Phase A requests. | | `/cross-research <target>` | Same auto-pick, named target. | | `/cross-research --with <id> [target]` | Override an auditor slot: `codex`, `gemini`, `opencode`, `aider`, `copilot`. Target optional. | | `/cross-research list` | Show roster with self marker. No requests generated. | | `/cross-research compare` | Read Phase A responses, build Phase B synthesis request, fire it, render matrix, archive. |

Smart target auto-detection (bare `/cross-research`)

When invoked without a target, run this detection cascade and use the first non-empty result:

1. **Staged changes** -- `git diff --cached --name-only` 2. **Unstaged changes** -- `git diff --name-only` 3. **Last commit** -- `git diff HEAD~1 --name-only` 4. If all empty: print the roster and ask "what topic would you like researched?"

Report which step succeeded:

Cross-research target auto-detected: 2 staged file(s)
  mcp-server/src/cross-dispatcher.js
  mcp-server/test-cross-dispatcher.js
(Override with /cross-research <path> or /cross-research --with <id> <path>.)

If >5 files, group in request body but list all paths. If a single file >2000 lines, use the diff hunks rather than the full file.

The natural-language phrase **"research this across models"** / **"multi-model research"** fires the intent router (`mcp-server/src/intent-router.js`), which nudges Claude to invoke `/cross-research` automatically -- same auto-detect flow runs.

Default flow -- Donahoe Trident (don't make me think)

Caller is one perspective. **Default is two independent research streams feeding one synthesis.** The Trident yields: independent evidence collection in parallel, then a single merge pass that exposes what each model knew, what they agreed on, and where they diverge.

When invoked, do this in order:

1. **Probe roster.** Call `pickAuditors({ count: 2, env: process.env })` from `audit-roster.js`. Returns `{ picks, missing, note }` -- picks are installed AND non-self.

2. **Show a TODO surface** in chat:

   Cross-research plan
     [ ] Step A.1: Generate Wave A requests (codex=benchmarks, gemini=citations)
     [ ] Step A.2: Fire codex in background
     [ ] Step A.2: Fire gemini in background
     [ ] Wait for both completions
     [ ] Step B.1: Generate Wave B synthesis request (claude=synthesis)
     [ ] Step B.2: Fire synthesis
     [ ] Step B.3: Render consensus/contested/unique matrix
     [ ] Step B.4: Archive all requests + responses + merge

3. **Ask the user once** which combo to run:

   Auditors detected and ready: codex, gemini.
   Run cross-research:
     [A] codex only (benchmarks angle)
     [B] gemini only (citations angle)
     [C] Both -- recommended (Donahoe Trident, enables full synthesis)
     [D] Cancel / pick custom

Default suggestion: **C (Both)** when >=2 installed. Synthesis (Phase B) requires both Phase A responses; if only one auditor runs, Phase B renders a partial synthesis and flags the gap.

4. **If only one installed:**

> "Only `<id>` is installed locally. The full Trident shines here -- two > independent research streams remove single-model blind spots before synthesis. > Install one of the available auditors (opencode, aider, etc.) to unlock the > complete picture."

Then offer to run the single-auditor partial flow.

5. **Fire Wave A in background** (see Wave A section below).

6. **After Wave A completes**, run `/cross-research compare` (or fire it automatically when both background jobs notify).

7. **Fire Wave B synthesis** via fresh Claude session (see Wave B section below).

8. **Render matrix** from `mergeResponses('research', responses)`.

9. **Archive** all files to `.ijfw/cross-audit/archive/<ts>-research/`.

Auditor picking

node --input-type=module -e "import('./mcp-server/src/audit-roster.js').then(m => console.log(m.formatRoster()))"

Default pick order (first non-self): `codex → gemini → opencode → aider → copilot → claude`.

Research role assignment is mode-aware via `assignRoles('research', roster, self)` in `cross-dispatcher.js`:

  • `codex` → `benchmarks` angle
  • `gemini` → `citations` angle
  • Synthesis always goes to a **fresh Claude session via `claude -p`** -- never the

caller's own session, even if self=claude, to prevent circularity.

---

Wave A -- Parallel fan-out

Step A.1 -- Generate Phase A requests via the dispatcher

Run one node call per auditor:

node --input-type=module -e "
import('./mcp-server/src/cross-dispatcher.js').then(m =>
  process.stdout.write(m.buildRequest('research', '<target>', 'codex', 'benchmarks'))
)" > .ijfw/cross-audit/request-research-codex.md
node --input-type=module -e "
import('./mcp-server/src/cross-dispatcher.js').then(m =>
  process.stdout.write(m.buildRequest('research', '<target>', 'gemini', 'citations'))
)" > .ijfw/cross-audit/request-research-gemini.md

> **Note:** `buildRequest` is synchronous and returns a string -- do NOT `.then()` it. Wrap it in `process.stdout.write(...)` directly.

Replace `<target>` with

Read more
Ships withijfw

IJFW — It Just F*cking Works. Ferrox Labs' local-first infrastructure for AI coding agents: shared memory, smart routing, multi-AI cross-audits, disciplined workflow.

Get the whole plugin