Instructions for working with Mortal Prompter, a Go CLI that orchestrates AI-vs-AI code review battles between Claude Code, Codex, and Gemini.
You are working with **Mortal Prompter**, a Go CLI tool that orchestrates iterative development loops between AI coding assistants. It creates a "battle" where an **Implementer** builds code and a **Reviewer** critiques it until no issues remain.
```
cmd/mortal-prompter/main.go # Entry point, CLI/TUI mode selection
internal/
├── orchestrator/ # Main "combat" loop between LLMs
├── fighters/ # Fighter implementations (claude, codex, gemini)
├── tui/ # Terminal UI (Bubble Tea)
│ ├── model.go # TUI state model
│ ├── view.go # Rendering logic
│ ├── update.go # Event handling
│ ├── events.go # Custom event types
│ ├── observer.go # Observer for orchestrator events
│ ├── styles.go # Lip Gloss styling
│ ├── keys.go # Key bindings
│ └── components/
│ └── healthbar.go # Health bar component
├── git/ # Git operations (diff, commit)
├── logger/ # Terminal + file logging
├── reporter/ # Markdown battle report generator
└── config/ # Configuration and flag parsing
pkg/types/ # Shared types (Round, SessionResult, etc.)
```
Users can choose any combination of fighters:
**Default:** Claude (implementer) vs Codex (reviewer)
**CLI flags:**
```bash
make build # Build for current platform
make install # Install to system
make build-all # Build for all platforms (darwin/linux/windows)
make test # Run tests
make clean # Clean build artifacts
make release-dry # Test release without publishing
```
1. User provides initial prompt (via TUI or `--prompt` flag)
2. User selects implementer and reviewer fighters
3. **Implementer** executes task (e.g., `claude -p "<prompt>"`)
4. Capture `git diff` of changes
5. **Reviewer** reviews diff and identifies issues
6. If issues found: construct new prompt with issues list, repeat from step 3
7. If no issues (LGTM): finish successfully
8. After max iterations: prompt for manual confirmation
The TUI uses three core functions:
```
ViewFighterSelect → ViewPrompt → ViewBattle → ViewResults
↓
ViewConfirmation
```
When adding a new `ViewState`, you MUST update:
1. **model.go**: Add the new `ViewState` constant
2. **view.go**: Add `case ViewNewState:` in `View()` and implement `viewNewState()`
3. **update.go**: Add `case ViewNewState:` in `handleKeyMsg()` and implement `handleNewStateKeys()`
**Checklist:**
The orchestrator sends real-time events to the TUI:
1. Events arrive through `eventChan`
2. `waitForEvent()` wraps them in `eventMsg`
3. `handleEvent()` processes them and updates model state
4. Must return `tea.Batch(m.spinner.Tick, tick(), waitForEvent(...))` to keep listening
States: `FighterIdle`, `FighterActive`, `FighterFinished`
Updated by:
1. **Missing keyboard handler**: Every ViewState needs a case in `handleKeyMsg()`
2. **Stale field names**: Use `implementerState/reviewerState` (not `claudeState/codexState`)
3. **Event payload missing data**: Check that payloads include all fields (e.g., `FighterActionPayload.Fighter`)
4. **UI alignment with ANSI**: Use `len(plainText)` for padding, not styled text
5. **Two-phase TUI**: App runs TWO separate TUIs - first for prompt input (quits on submit), second for battle display
Session logs and reports written to `.mortal-prompter/`:
**Log file usage:**
1. **When adding new views**: Follow the checklist above - all three files must be updated
2. **When handling events**: Always return `tea.Batch()` with `waitForEvent()` to keep event stream alive
3. **When rendering UI**: Calculate padding using plain text lengths, not ANSI-styled strings
4. **When updating fighter states**: Ensure event payloads include both `Fighter` and `Action` fields
5. **When debugging**: Check `.mortal-prompter/session-*.log` for complete execution trace
6. **When testing locally**: Use `make build && ./mortal-prompter` for quick iteration
7. **Before release**: Run `make release-dry` to test packaging
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/mortal-prompter-guide/raw