MultiShooter
MultiShooter is a narrow, active-only review surface for Codex. A skill or tool publishes the evidence needed for the current decision; the user reads and answers in a calm vertical browser view; a typed receipt returns to the owning Codex flow. The browser stores no decision history.
The first slice supports prose, one or more raster images, choice/approval asks, one active review process, and a manual-link fallback. It deliberately excludes archives, dashboards, generic document editing, sharing, and transcript scraping.
Quickstart
Prerequisites: Bun 1.3 or newer and this trusted project checkout.
bun install
bun run doctor
bun run example:hello -- --manual-link
Open the one printed loopback URL, choose an answer, and submit it. The CLI prints the typed receipt, holds the acknowledgement briefly, closes the server, and removes the active browser state.
Without --manual-link, the example opens the operating-system browser. That
does not claim native Codex-browser support. The project-scoped MCP server
returns the URL so Codex can open it in its own browser pane.
Install as a Codex plugin
Prerequisite: Bun 1.3 or newer, and Codex CLI v0.142.0 or newer for the
root-local marketplace path (source.path: "./").
Add this repository as a marketplace:
codex plugin marketplace add jnyross/MultiShooter
Open /plugins in Codex, select the MultiShooter marketplace, and install
the MultiShooter plugin. Start a new Codex session after installation so
its bundled MCP tools are discovered.
The portable package follows
Agent Plugins 1.0: plugin.json
identifies the plugin and mcp.json declares its local MCP server. Codex uses
the repository marketplace only for distribution. The installed plugin runs
the bundled dist/mcp.js with dist/renderer/*; it does not depend on
checkout-local paths or a generated Codex config.
For development from a trusted source checkout, generate the checkout-local Codex MCP registration:
bun install
bun run codex:sync-config
.codex/config.toml is a development fallback with absolute paths for the
current checkout. Start a new Codex session after changing it. The Mac mini
dogfood lab notes live in docs/dogfood/mac-mini-lab.md.
The tools are:
multishooter_doctormultishooter_presentmultishooter_present_gstack_plan_designmultishooter_answermultishooter_waitmultishooter_close
The MCP server supports one active surface. present returns a capability URL,
present_gstack_plan_design maps one gstack decision brief into the validated
v0 contract without asking the skill to hand-author packet JSON,
answer lets Codex answer one explicit ask through the same stale/idempotency
validation as the browser, wait performs bounded 25-second reads, and close
revokes the current state. MCP receipt delivery is classified
trusted_unverified because Codex does not expose transcript-delivery proof.
Author API
import {
CallbackHostAdapter,
choice,
option,
presentReview,
prose,
} from "./src";
const session = await presentReview(
{
title: "Choose the interaction model",
evidence: [prose("Keep Codex primary and the review active-only.")],
ask: choice("interaction model", [
option("vertical", "Vertical review workspace", {
recommended: true,
}),
option("canvas", "Open canvas"),
]),
},
{
hostAdapter: new CallbackHostAdapter((receipt) => {
console.log(JSON.stringify(receipt));
}),
},
);
console.log(session.url);
const answer = await session.waitForAnswer();
await session.acknowledgeAndClose(answer);
A recommendation is never a selection. Submission remains disabled until the user deliberately chooses an answer.
CallbackHostAdapter callbacks must synchronously complete their receipt side
effect; use the optional abort signal to stop before writing. Async callbacks
are rejected so a timed-out delivery cannot be reported as verified after the
callback continues in the background.
For image evidence, use a logical assetId in the packet and pass a generated
artifact root plus its root-relative path:
const session = await presentReview(packet, {
assets: {
root: "/absolute/generated-artifacts",
paths: { "hero-image": "hero.png" },
},
});
The browser receives only a fresh opaque asset ID; filesystem paths never enter the page.
Development
bun run typecheck
bun run test
bun run test:e2e
bun run build
The Playwright test exercises 600, 720, and 800px layouts, keyboard-operable controls, deliberate selection, response delivery, and axe accessibility.
Documentation
- Quickstart
- Concepts
- Authoring packets
- Lifecycle
- Configuration
- Errors
- Security
- Host compatibility
- gstack plan-design-review adapter
- Initial benchmarks
- First dogfood scorecard
- gstack plan-design adoption scorecard
- Troubleshooting
- Plannotator assessment
Plannotator-derived lifecycle code and its MIT notice are recorded in THIRD_PARTY_NOTICES.md.