A panel of advocates for hard decisions.
Convene three voices. Argue it out. Commit the record.
You have a decision to make. You want more than one perspective, with real disagreement baked in, and a written record at the end. Tribune convenes three advocates — a Proposer, a Skeptic, and a Red Team — argues it out, streams each voice to your terminal, and writes an ADR you can commit to your repo.
Not a chatbot. Not an SDLC framework. A decision instrument.
tribune ask "Should we migrate the audit log to Postgres or keep SQLite?"
The logo is the panel. Each vertex is a voice.
Tribune uses your AI CLI subscriptions, not API keys. Each voice shells out to whichever CLI the panel specifies.
# Required: Claude Code (used by the default panel)
# https://docs.claude.com/en/docs/claude-code/overview
claude --version
# Optional: Codex CLI + Gemini CLI (needed for --panel cross-provider)
codex --version
gemini --version
# Install Tribune
pip install tribune-cli
# Not on PyPI yet? Install direct from GitHub:
pip install git+https://github.com/ao92265/tribune.gitNo ANTHROPIC_API_KEY required. No billing surprises.
tribune ask "Should we migrate the audit log to Postgres or keep SQLite?"
tribune ask "Which auth library for the new service?" --context ./notes.md
tribune ask "Kill or keep the batch import feature?" --out ./adr
# Pick a panel (see Panels below)
tribune ask "..." --panel cross-provider
tribune ask "..." --panel linus
# Iterate rounds
tribune ask "..." --rounds 3 # fixed: three Proposer→Skeptic→Red Team rounds
tribune ask "..." --auto # iterate until a Judge voice replies STABLE
tribune ask "..." --auto --max-rounds 8 # cap auto-iteration (default: 5)
# Print verdict to stdout instead of writing an ADR
tribune ask "..." --no-adrThree advocates speak in turn, streamed live. When they're done, Tribune writes a markdown ADR to ./decisions/ with the verdict and the strongest unresolved objection.
Commit it. Review it in six months. See whether the Red Team was right.
By default each voice speaks once. For harder decisions, add more rounds:
--rounds N— run N sequential Proposer→Skeptic→Red Team rounds before synthesis. Each round sees the full prior transcript.--auto— after each round, a Judge voice reads the transcript and decides whether the panel has converged. When the Judge repliesSTABLE, Tribune stops and synthesises the verdict. Capped by--max-rounds(default 5) so it cannot run forever.
The Judge is a fourth voice that reuses the panel's synth bin/model. It never appears in the ADR — it only decides when to stop. Use --auto when you don't know up front how many rounds the question needs.
--no-adr prints the full transcript and verdict to stdout and does not write a file. Useful when you want a second opinion in-session and don't want ./decisions/ to grow. The Claude Code /tribune slash command passes this by default so the breakdown stays in chat.
Convene a tribune without leaving your Claude Code session. Copy the slash command into your global commands directory:
mkdir -p ~/.claude/commands
curl -fsSL https://raw.githubusercontent.com/ao92265/tribune/main/.claude/commands/tribune.md \
-o ~/.claude/commands/tribune.mdThen from any Claude Code session:
/tribune Should we migrate the audit log to Postgres or keep SQLite?
Claude will shell out to tribune ask, stream the three advocates, and offer to commit the ADR.
Each voice speaks in sequence. Later voices see earlier voices.
flowchart LR
Q["`**Question**
(+ optional context)`"] --> P
P["`**Proposer**
_opus_
defend a position`"] --> S
S["`**Skeptic**
_sonnet_
attack the reasoning`"] --> R
R["`**Red Team**
_opus_
predict the failure`"] --> V
V["`**Verdict synthesis**
_opus_`"] --> A["`**ADR**
decisions/YYYY-MM-DD-slug.md`"]
style P fill:#111,color:#fff
style S fill:#6b7280,color:#fff
style R fill:#b91c1c,color:#fff
style V fill:#fef3c7,color:#111
style A fill:#e0f2fe,color:#111
Why Sonnet for the Skeptic? Different model → genuine divergence, not three flavours of the same voice. The Skeptic is the hardest role; if it's weak, Tribune is just a fancier chatbot.
Context flows forward. Nobody sees the Verdict except the reader of the ADR.
sequenceDiagram
autonumber
participant U as You
participant P as Proposer
participant S as Skeptic
participant R as Red Team
participant V as Verdict
U->>P: question + context
P-->>U: stream argument
U->>S: question + context + Proposer
S-->>U: stream critique
U->>R: question + context + Proposer + Skeptic
R-->>U: stream failure prediction
U->>V: everything above
V-->>U: verdict + minority report
Note over U: Write ADR to ./decisions/
Tribune writes an ADR. You own what happens to it.
stateDiagram-v2
[*] --> proposed: tribune ask "..."
proposed --> accepted: you commit to it
proposed --> rejected: Skeptic / Red Team was right
accepted --> superseded: new decision replaces it
accepted --> vindicated: Red Team was wrong at 6-month review
rejected --> [*]
superseded --> [*]
vindicated --> [*]
A panel is the roster of voices Tribune convenes. You can use a built-in panel, write your own, or install someone else's.
| Name | Voices |
|---|---|
default |
Claude Opus (Proposer, Red Team, Synth) + Claude Sonnet (Skeptic). |
cross-provider |
Claude Proposer + Codex Skeptic + Gemini Red Team + Claude synth. Genuine provider divergence. |
Streaming: Claude and Gemini voices stream token-by-token. The Codex voice captures its final message cleanly (codex stdout is too noisy to stream raw), so expect a pause before the Codex block appears — then the full response in one burst.
List, inspect, and install:
tribune panel list
tribune panel show default
tribune panel install ./examples/panels/linus.tomlPanels are TOML files. Drop them in ~/.config/tribune/panels/ or ./.tribune/panels/ and Tribune picks them up. Minimal shape:
name = "linus"
description = "Principled-engineer trio."
[proposer]
bin = "claude" # one of: claude | codex | gemini
model = "opus" # optional; CLI default if omitted
system = """
You are an experienced kernel maintainer ...
"""
[skeptic]
bin = "claude"
model = "sonnet"
system = """..."""
[red_team]
bin = "claude"
model = "opus"
system = """..."""
[synth]
bin = "claude"
model = "opus"
system = """..."""See examples/panels/linus.toml for a full working example.
A panel is one file. Share it like any file:
# Someone sends you linus.toml or you find it in a repo
tribune panel install ./linus.toml
tribune ask "..." --panel linusTribune verifies the TOML parses and the voices are valid before it installs.
Convene the panel on code, not just decisions.
git add -p # stage the changes you want reviewed
tribune review # review staged diff
tribune review --ref HEAD # review the last commit
tribune review --ref HEAD --panel cross-providerTribune asks: "Should this diff be committed as-is, or does it hide a regression, scope-creep, or a failure mode a future maintainer will curse you for?" Proposer argues ship-it. Skeptic attacks the reasoning. Red Team predicts the bug in six months. Synth picks.
Wire it into your pre-commit hook if you want every commit on the record:
#!/bin/sh
# .git/hooks/pre-commit
tribune review --out ./decisions || exit 1Tribune will not install the hook for you. Your repo, your call.
A file at ./decisions/YYYY-MM-DD-slugified-question.md:
# Decision: Wraith audit log storage
Date: 2026-04-22
Status: proposed
Panel: default
## Question
Should Wraith use Postgres or SQLite for the audit log?
## Context
_No context provided._
## Panel
### Proposer — claude:opus
Use Postgres. The audit log will be queried by compliance reviewers ...
### Skeptic — claude:sonnet
The Proposer assumes the compliance query pattern exists. Today there is ...
### Red Team — claude:opus
This fails when the ops team doesn't budget a Postgres instance ...
## Verdict
Use Postgres, but only after the first real compliance query lands ...
## Minority report
"The Proposer assumes the compliance query pattern exists."Each advocate's header records the CLI and model used — so when you come back to the ADR in six months, you know exactly which voice said what.
Most AI dev tools collaborate. They agree with you, build what you ask, and ship. That's fine for code. It's dangerous for decisions.
Every serious decision needs a dissent. Tribune forces it.
Inspired by the Roman tribunes who spoke for the plebeians against the senate. Your advocate, on the record.
- Three advocates on every decision. Synthesis writes the verdict.
- Subscription auth via
claude/codex/geminiCLIs. No API keys. - Built-in
defaultandcross-providerpanels. - Custom personas via TOML files.
- Shareable rosters (
tribune panel install <file>). - Git diff review (
tribune review). - Fixed rounds (
--rounds N) or Judge-driven iteration until stable (--auto). - Print-only mode (
--no-adr) for in-session second opinions. - ADR file you commit to your repo.
- Claude Code slash command (
/tribune).
These aren't roadmap items. They're design decisions.
- No web UI. Tribune is a decision instrument, not a chatbot.
- No hosted service. Your decisions belong in your repo, not someone else's database.
- No telemetry. Tribune never phones home. Your questions are yours.
Anything in this list would be a different product.
MIT.