outlAIer is a spectator game where multiple AI models play an "impostor" social deduction round in public. One model picks the secret word, one player is left out, everyone gives clues, then the table votes.
The UI copy is currently in French. The codebase and setup are documented in English so the project can be reused or relaunched by other teams.
- Live game view powered by Convex subscriptions
- History pages for completed games
- Leaderboard tracking model performance across rounds
- Local CLI runner for quick simulations and prompt debugging
- Shared prompt/model definitions used by both the web app and backend
- Next.js 15 App Router
- React 19
- Tailwind CSS 4
- Convex for data, scheduling, and realtime updates
- OpenRouter for model completions
- pnpm for package management
- Node.js 20+
- pnpm 10+
- A Convex account and deployment
- An OpenRouter API key
-
Install dependencies:
pnpm install
-
Create the local CLI env file:
cp .env.example .env
-
Create or link a Convex deployment:
pnpm exec convex devThis usually creates or updates
.env.localwithCONVEX_DEPLOYMENTandNEXT_PUBLIC_CONVEX_URL. -
If
.env.localwas not created automatically, create it from the example and fill in the Convex values manually:cp .env.example .env.local
-
Keep environment variables in the right place:
-
.env.localUsed by Next.js locally. Must includeNEXT_PUBLIC_CONVEX_URL. -
.envUsed by the CLI runner inscripts/game-cli.ts. Must includeOPENROUTER_API_KEY. -
Convex deployment environment Set
OPENROUTER_API_KEYandCONVEX_GAME_LOOP_ENABLEDwith:pnpm exec convex env set OPENROUTER_API_KEY your-openrouter-api-key pnpm exec convex env set CONVEX_GAME_LOOP_ENABLED false
-
-
Start the app:
pnpm dev
-
In another terminal, keep the Convex dev process running:
pnpm exec convex dev
Open http://localhost:3000.
- Required by the Next.js app
- Used by the React Convex client to connect the UI to your deployment
- Usually generated by
pnpm exec convex dev
- Used by the Convex CLI to know which deployment the project is linked to
- Usually generated by
pnpm exec convex dev
- Required for the hosted Convex game loop
- Required for the local CLI when you run
pnpm game - Not required for
pnpm game:mock
- Controls whether the automated game loop is allowed to run inside Convex
- Read by
convex/gameLoop.ts,convex/admin.ts, andconvex/crons.ts - Accepted values in practice:
true: the loop can start, schedule the next game, and recover stuck gamesfalse: Convex skips loop execution and recovery scheduling
Recommended usage:
- Local development: keep it
false - Public deployment with autoplay enabled: set it to
true - Maintenance window or cost control: set it back to
false
Examples:
pnpm exec convex env set CONVEX_GAME_LOOP_ENABLED true
pnpm exec convex env set CONVEX_GAME_LOOP_ENABLED falseThe public UI is read-only. Actual game generation happens in Convex internal actions.
-
Local mock simulation:
pnpm game:mock
-
Local simulation with OpenRouter:
pnpm game -- --verbose
-
Hosted automated loop: Set
CONVEX_GAME_LOOP_ENABLED=truein your Convex deployment env.
The recovery cron in convex/crons.ts will keep the loop alive. If you need the very first game immediately, run internal.admin.startGameLoop from the Convex dashboard after seeding the deployment.
When CONVEX_GAME_LOOP_ENABLED=false, the following Convex behavior is intentionally disabled:
internal.gameLoop.runGameexits earlyinternal.admin.startGameLooprefuses to start the loop- the recovery cron does not restart abandoned or missing games
The local CLI lives in scripts/game-cli.ts. It is useful for prompt iteration, local simulations, and debugging model behavior without using the web UI.
pnpm game
pnpm game:mock--mockUse the mock provider instead of OpenRouter. Useful for deterministic local testing without API calls.--verbosePrint shortened prompt contents for each model call.--debugPrint full prompt/response details, token usage, latency, and provider/model metadata.--iterations=<n>Run multiple games in sequence and print a final summary. Example:pnpm game -- --iterations=10--players=<list>Override the default roster with a comma-separated list of model ids. Example:pnpm game -- --players=claude,gpt,gemini,mistral
Run one local mock game:
pnpm game:mockRun five real games and print a summary:
pnpm game -- --iterations=5Run with detailed prompt inspection:
pnpm game -- --debugRun a custom roster in mock mode:
pnpm game:mock -- --players=claude,gpt,llama,mistral --iterations=3- Each run writes a
.jsonllog file underlogs/ - Logs include prompts, model responses, token usage, latency, and iteration metadata
- Review those files before sharing them publicly because they may contain generated content you do not want to publish
pnpm dev- start the Next.js apppnpm build- production buildpnpm lint- run ESLintpnpm typecheck- run TypeScript checkspnpm check- lint + typecheckpnpm audit- production dependency auditpnpm game- run the local CLI against OpenRouterpnpm game:mock- run the local CLI with the mock provider
src/app- Next.js routessrc/components/game- live game UIconvex- backend queries, mutations, internal actions, and cron recoveryshared- shared models, prompts, and word listsscripts/game-cli.ts- local simulation runner
The main extension points are:
shared/models.tsto change participating models and provider IDsshared/word-list.tsto change the game vocabularyshared/promptsto tune host, clue, and vote behavioroutlaier.config.tsto change the default roster and local log directory
If you fork the project for public deployment, update the OpenRouter headers in src/lib/openrouter.ts and convex/lib/openrouter.ts so they point to your own domain/app name.
- Do not commit
.env,.env.local, or any deployment credential. - CLI runs write prompt/response logs to
logs/. Review them before sharing because they contain model outputs and token metadata. - The app currently exposes public read queries only. If you add user-triggered mutations or admin controls, add auth before exposing them.
- See
SECURITY.mdfor disclosure guidance.
See CONTRIBUTING.md.
This repository is released under the 0BSD license. See LICENSE.
