Skip to main content

Automated multi-agent code review tool for GitHub PRs

Project description

MARX - Multi-Agentic Review eXperience

Build status MIT License Python

An interactive CLI tool for automated multi-model AI code review of GitHub Pull Requests. Marx fetches open PRs and runs parallel code reviews inside Docker using three AI models (Claude, Codex, and Gemini) without modifying your local repository.

TL;DR: Install, Configure, Run

# 1) Install (no checkout needed)
uv tool install marx-ai

# 2) Configure credentials
cat > ~/.marx <<'EOF'
GITHUB_TOKEN=ghp_your_token_here
ANTHROPIC_API_KEY=your_claude_key
OPENAI_API_KEY=your_openai_key
GEMINI_API_KEY=your_gemini_key
# Optional: override repo detection
# MARX_REPO=owner/repo
EOF

# 3) Run on a repo with all agents
cd /path/to/your/git/repo
marx --pr 123 --agents claude,codex,gemini

Features

  • Multi-Model AI Review: Runs Claude, Codex, and Gemini in parallel for comprehensive code analysis
  • Containerized Checkout: Clones the PR branch inside Docker so your local repo stays untouched
  • Intelligent PR Filtering: Automatically filters PRs where you're not the author or reviewer
  • Docker Isolation: All AI models run in containers with proper permissions
  • Structured Output: JSON-formatted results with priority-based issue categorization
  • Robust Error Handling: Graceful fallbacks and comprehensive validation
  • User-Friendly Interface: Colored output with clear progress indicators

Prerequisites

The following tools must be installed:

  • git - Version control
  • gh - GitHub CLI (must be authenticated)
  • docker - Container runtime

Installation

Option 1: Install the published package from PyPI

If you simply want to use Marx and do not need the repository checked out locally, install the published package directly from PyPI using uv:

# Install globally
uv tool install marx-ai

# Or run without installing
uvx marx-ai

After installation the marx CLI will be on your PATH and you can run marx --help to verify everything is set up correctly.

Option 2: Using Nix (Recommended for development)

If you have Nix with flakes enabled:

# Clone the repository
git clone https://github.com/forketyfork/marx.git
cd marx

# Install globally to your profile
nix profile install .

# Or run without installing
nix run .

# Or enter development environment
nix develop

Option 3: From source with uv

For standard Python environments when working from a clone of the repository:

# Clone the repository
git clone https://github.com/forketyfork/marx.git
cd marx

# Install globally
uv pip install .

# Or install in editable mode for development
uv pip install -e ".[dev]"

Note: If you're using Nix, uv pip install will fail because Nix's Python environment is read-only. Use the Nix installation methods above instead.

Running Marx

After installation, run:

marx

Quick Start with Nix (Recommended for Development)

If you have Nix with flakes enabled:

# Clone the repository
git clone https://github.com/forketyfork/marx.git
cd marx

# Enter the development environment
nix develop

# Or use direnv for automatic environment loading
direnv allow

The Nix flake provides:

  • Python 3.12 with all dependencies
  • System tools (git, gh, docker)
  • Development tools (pytest, black, ruff, mypy)
  • Just command runner for common tasks

Using Just Commands

# See all available commands
just

# Run linters
just lint

# Run tests
just test

# Run marx
just run

# Cut a release (updates versions, commits, tags, pushes)
just release v0.1.1   # creates and pushes branch release-0.1.1 and tag v0.1.1

# Install package in editable mode
just install

# Run all checks (CI equivalent)
just check

Environment Variables

Setting up Environment Variables

Copy the example environment file and fill in your credentials:

cp .env.example .env
# Edit .env with your API keys and tokens

If using direnv (recommended), the .env file will be automatically loaded.

Required

  • GITHUB_TOKEN - GitHub API token (required for container access to GitHub API)

API Keys (at least one required)

The following API keys enable the respective AI models to function. You can provide one or more:

  • ANTHROPIC_API_KEY - Anthropic API key for Claude
  • OPENAI_API_KEY - OpenAI API key for Codex
  • GOOGLE_API_KEY or GEMINI_API_KEY - Google API key for Gemini

Without API keys, the AI models will fall back to using local configuration from ~/.claude, ~/.codex, or ~/.gemini directories if available.

Optional

  • MARX_REPO - Optional owner/name override (e.g., owner/repo) when auto-detection fails

Configuration

Marx supports two authentication methods for AI models:

Method 1: API Keys (Recommended for CI/CD)

Set environment variables with your API keys:

export ANTHROPIC_API_KEY="your-key-here"
export OPENAI_API_KEY="your-key-here"
export GOOGLE_API_KEY="your-key-here"

Method 2: Local Configuration Directories

Marx can use AI model configuration directories from your home directory:

  • ~/.claude - Claude CLI configuration
  • ~/.codex - Codex CLI configuration
  • ~/.gemini - Gemini CLI configuration

These directories are mounted read-only into the Docker container during execution. This method is useful for development when you've already authenticated via the respective CLI tools.

Global Config File (~/.marx)

Marx also looks for a configuration file at ~/.marx. Any values defined here act as defaults and are only applied when the corresponding environment variable is unset. The file uses a simple KEY=value format and supports comments starting with # on their own line.

Example:

# Default repository for GitHub operations
MARX_REPO=acmecorp/my-app

# API keys (omit or override with environment variables as needed)
GITHUB_TOKEN=ghp_example
OPENAI_API_KEY="sk-123"

This file is loaded automatically when the CLI starts. Environment variables still take precedence, allowing you to override individual values for a single run.

Customizing the review prompt

The default review instructions provided to each agent are stored in the package at marx/prompts/review_prompt.md. You can supply your own prompt template by either setting the MARX_REVIEW_PROMPT_PATH environment variable or adding REVIEW_PROMPT_PATH=/path/to/prompt.md to your ~/.marx configuration file. The template supports the placeholders {pr_number}, {repo}, {commit_sha}, {agent}, and {container_workspace_dir}, which are replaced at runtime.

Deduplication prompt

When more than one agent is selected, Marx automatically invokes an agent for a follow-up deduplication pass. By default, the first agent in the --agents list is used, but you can override this with the --dedupe-with option. This step reads the individual review outputs, asks the agent to merge duplicate issues, and writes the consolidated results to runs/<pr>/dedup-review.json, ensuring the agent field lists all reporting agents as a comma-separated value. You can customize the deduplication instructions by providing a template at MARX_DEDUP_PROMPT_PATH or DEDUP_PROMPT_PATH (in ~/.marx). The bundled template lives at marx/prompts/dedup_prompt.md. The Docker runner copies this file from .marx/dedup-review.json in the workspace back to the run directory, so keep custom output names aligned with that location. The template is rendered with Python string formatting, so escape any literal braces as {{ and }} when editing to avoid malformed prompts.

Usage

marx [OPTIONS]

Use marx --help for a quick reminder of prerequisites, environment variables, and example commands.

Options

  • --help - Show help message and exit
  • --version - Show version and exit
  • --pr <number> - Specify PR number directly (skip interactive selection)
  • --agents <agents> - Comma- or space-separated list of agents to run (claude, codex, gemini). Append :<model> to override the model used by that agent.
    • Default: all agents
    • Claude accepts aliases like opus, sonnet, and haiku, or full release identifiers such as claude-sonnet-4-5-20250929. See the Claude models documentation for available models.
    • Codex works with OpenAI models including gpt-5 and gpt-5-codex, plus any custom providers configured in ~/.codex/config.toml.
    • Gemini supports model IDs such as gemini-2.5-flash-lite, gemini-2.5-flash, and gemini-2.5-pro. See the Gemini models documentation for the complete list of available models.
  • --repo <owner/repo> - Repository in the format owner/repo (e.g., acmecorp/my-app)
    • Overrides automatic repository detection
  • --resume - Reuse artifacts from the previous run and skip AI execution
  • --dedupe-with <agent> - Agent to use for deduplication (claude, codex, gemini). Append :<model> to override the model.
    • Default: first agent from --agents

Examples

# Interactive mode with all agents (default)
marx

# Review PR #123 with all agents
marx --pr 123

# Review PR #123 with Claude only
marx --pr 123 --agents claude

# Interactive mode with Codex and Gemini
marx --agents codex,gemini

# Run Claude Opus with Codex defaults
marx --agents "claude:opus,codex"

# Review with Gemini 2.5 Pro only
marx --agents "gemini:gemini-2.5-pro"

# Review PRs in specific repository
marx --repo acmecorp/my-app

# Review specific PR in specific repository
marx --pr 123 --repo acmecorp/my-app

# Review specific PR with custom Claude + Gemini models
marx --pr 456 --agents "claude:sonnet,gemini:gemini-1.5-pro"

# Resume from previous run without rerunning agents
marx --resume --pr 123

# Use Claude Opus for deduplication while running all agents
marx --pr 123 --dedupe-with claude:opus

# Run Codex and Gemini, use Claude for deduplication
marx --agents codex,gemini --dedupe-with claude

How It Works

1. Setup & Validation

  • Checks for required dependencies (git, gh, docker)
  • Builds the configured Docker image (default: marx:latest) if not present
  • Validates GITHUB_TOKEN environment variable
  • Confirms current directory is a git repository

2. Repository Detection

Determines repository slug (owner/name) using three methods in order:

  1. MARX_REPO environment variable
  2. gh repo view command
  3. Git remote URL parsing (fallback)

3. PR Discovery

  • Gets current GitHub user via GitHub API
  • Fetches open PRs with metadata (title, author, reviewers, line changes)
  • Filters PRs where:
    • You are NOT the author
    • You are NOT a reviewer
    • Has at least one reviewer assigned
  • Handles both flat array and nested nodes[] API response formats

4. PR Selection & Checkout

  • If --pr is specified: validates PR exists and gets branch name
  • Otherwise: displays formatted PR list with colors and statistics and prompts for selection
  • Fetches the PR and gets commit SHA
  • Clones the repository inside the Docker container and checks out the PR head (or specific commit SHA)

5. Parallel AI Code Review

  • If --agents is specified: runs only the selected agents
  • Otherwise: runs all three agents (claude, codex, gemini)

Each AI model receives a detailed prompt instructing it to:

  • Gather PR context using gh commands
  • Review code for bugs, security issues, performance problems, etc.
  • Output findings in structured JSON format

Selected models run simultaneously in isolated Docker containers with:

  • Repository clone inside the container
  • Run artifacts directory mounted from the host
  • Config directories from home
  • GitHub token for API access

6. Results Merging & Display

  • Validates all JSON outputs
  • Merges reviews from all three models
  • Sorts issues by priority (P0 → P1 → P2)
  • Displays formatted output with:
    • PR summary and title
    • Description from each AI model
    • Issue counts by priority
    • Detailed issue breakdown

Output Format

Review JSON Structure

Each AI model produces JSON output with this structure:

{
  "pr_summary": {
    "number": 123,
    "title": "PR Title",
    "description": "Brief description of changes"
  },
  "issues": [
    {
      "agent": "claude|codex|gemini",
      "priority": "P0|P1|P2",
      "file": "path/to/file.js",
      "line": 42,
      "category": "bug|security|performance|quality|style",
      "description": "Detailed description of the issue",
      "proposed_fix": "Concrete suggestion on how to fix it"
    }
  ]
}

Priority Definitions

  • P0 (Critical): Must be fixed - security vulnerabilities, bugs causing crashes/data loss
  • P1 (Important): Should be fixed - logic bugs, performance problems, poor error handling
  • P2 (Nice-to-have): Suggestions - code style, minor optimizations

Output Files

All files are saved in the run artifacts directory (runs/pr-{number}-{branch}/):

  • claude-review.json - Claude's review
  • codex-review.json - Codex's review
  • gemini-review.json - Gemini's review
  • dedup-review.json - Deduplicated issues when multiple agents run
  • merged-review.json - Combined review from all models

Example Workflow

# Run marx
marx

# The tool will:
# 1. Detect your repository
# 2. Show available PRs
# 3. Prompt you to select one
# 4. Clone the PR inside Docker and run AI reviews in parallel
# 5. Display merged results and write artifacts to runs/pr-<number>-<branch>/

# If you want a local checkout to apply fixes:
gh pr checkout 123

# Review artifacts are available at:
ls runs/pr-123-<branch>/

Docker Image

Marx uses a Docker image containing:

  • AI CLI Tools: Claude, Codex, Gemini
  • GitHub Tools: gh (GitHub CLI)
  • Search & Navigation: rg (ripgrep), fd, tree
  • Code Refactoring: fastmod, ast-grep (with sg alias)
  • Development Tools: git and other utilities

The image is built automatically on first run using the Dockerfile in this repository.

Customizing the Docker image

You can run Marx with a different Docker image by setting the MARX_DOCKER_IMAGE environment variable or by adding DOCKER_IMAGE=your/image:tag to your ~/.marx configuration file. The environment variable takes precedence over the config file, and both fall back to the bundled marx:latest image when unspecified.

When supplying a custom image make sure it satisfies the baseline requirements expected by the runner script:

  • A Linux base with /bin/bash, core utilities, and the ability to create users via useradd
  • git and gh (GitHub CLI)
  • Search and navigation tools: rg, fd, tree
  • Code editing helpers: fastmod, ast-grep (available as sg)
  • The CLI tools for any agents you intend to run (claude, codex, gemini)

Images missing these tools will fail at runtime, so verify your custom build before invoking Marx.

Error Handling

Marx includes robust error handling:

  • Non-JSON outputs from AI models are handled gracefully with empty reviews
  • Failed API calls are caught and reported with detailed error messages
  • Docker errors and container stderr are both captured and displayed
  • Invalid JSON is replaced with valid fallback structures
  • All temporary files are cleaned up automatically
  • Helpful hints are provided when authentication or configuration issues occur

Security Considerations

  • AI models run in isolated Docker containers
  • Config directories are mounted read-only
  • GitHub token is passed as an environment variable
  • No destructive git operations are performed
  • User input is validated before use

Troubleshooting

"GITHUB_TOKEN environment variable is not set"

Set your GitHub token: export GITHUB_TOKEN=ghp_your_token_here

"Unable to determine repository automatically"

Set the repository manually: export MARX_REPO=owner/repo

"Missing required dependencies"

Install the missing tools listed in the error message.

AI model fails or returns non-JSON output

Marx will automatically handle this by creating an empty review. Error details are displayed in the terminal output, including:

  • Docker errors (if Docker command failed)
  • Container stderr output (errors from the AI CLI tool)
  • Helpful hints for common issues (missing/invalid credentials)

Common causes:

  • Missing authentication: Set API key environment variables (e.g., ANTHROPIC_API_KEY) or run the CLI auth command (e.g., claude auth for Claude)
  • Invalid API keys or credentials in ~/.claude/, ~/.codex/, or ~/.gemini/
  • Network connectivity issues
  • API quota/rate limiting

Tip: For CI/CD environments, using API key environment variables is more reliable than local configuration directories.

Development & Testing

Nix Development Workflow (Recommended)

The project includes a Nix flake for reproducible development environments:

# Enter development shell
nix develop

# Or use direnv for automatic loading (recommended)
echo "use flake" > .envrc
direnv allow

# Use just for common tasks
just             # List all commands
just check       # Run all checks (lint + type-check + test)
just lint        # Run linters
just test        # Run tests
just run --pr 123  # Run marx

Setting up direnv

  1. Install direnv: nix-env -iA nixpkgs.direnv or see direnv installation
  2. Add hook to your shell (e.g., eval "$(direnv hook bash)" for bash)
  3. Allow the directory: direnv allow

Now the environment will automatically load when you cd into the project!

Just Command Reference

just install       # Install package in editable mode
just lint          # Run all linters (black, ruff, mypy)
just format        # Format code with black
just fix           # Auto-fix linting issues
just test          # Run all tests
just test-cov      # Run tests with coverage
just test-file FILE  # Run specific test file
just clean         # Clean build artifacts
just docker-build  # Build Docker image
just info          # Show environment info

Python Version

The Python codebase includes a comprehensive test suite. To run tests manually:

# Install development dependencies
uv pip install -e ".[dev]"

# Run tests with coverage
pytest

# Run tests with verbose output
pytest -v

# Run specific test file
pytest tests/test_github.py

# Type checking with mypy
mypy marx

# Code formatting with black
black marx tests

# Linting with ruff
ruff check marx tests

Project Structure

marx/
├── marx/          # Main package
│   ├── __init__.py
│   ├── cli.py          # CLI entry point and orchestration
│   ├── config.py       # Configuration and constants
│   ├── docker_runner.py # Docker container orchestration
│   ├── exceptions.py   # Custom exceptions
│   ├── github.py       # GitHub API client
│   ├── review.py       # Review processing and merging
│   └── ui.py           # Terminal UI and formatting
├── tests/              # Test suite
│   ├── conftest.py     # Pytest fixtures
│   ├── test_github.py  # GitHub client tests
│   └── test_review.py  # Review processing tests
├── pyproject.toml      # Project configuration
├── requirements.txt    # Dependencies
└── README.md           # This file

Publishing

Marx ships with an automated publication pipeline defined in .github/workflows/publish.yml. The workflow builds source and wheel distributions and uploads them as a workflow artifact on every run. Because uploading artifacts requires elevated GitHub token capabilities, the workflow explicitly grants the actions: write permission at the workflow level. When a GitHub release is published, the same workflow also pushes the distributions to PyPI using the PYPI_API_TOKEN repository secret.

Preparing a release

  1. Update the version number in pyproject.toml.
  2. Run just build locally to confirm the package can be built.
  3. Commit and push the release changes, then create a Git tag (for example v1.2.3).
  4. Draft a GitHub release for the tag and click Publish to trigger the PyPI deployment.

Configuring credentials

  • Create a PyPI API token.
  • Add the token to the repository secrets as PYPI_API_TOKEN (set the username to __token__).
  • Ensure the token has permission to upload to the marx-ai project on PyPI.

Manual runs of the workflow via Run workflow in the Actions tab will build and attach the distributions without publishing them, making it easy to validate the packaging process before performing a release.

Contributing

Contributions are welcome! Please ensure:

  • Code passes mypy type checking
  • Code passes ruff linting
  • Code is formatted with black
  • Tests pass with pytest
  • New features include tests
  • Follow Python best practices and PEP 8

License

See LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

marx_ai-0.1.2.tar.gz (41.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

marx_ai-0.1.2-py3-none-any.whl (33.5 kB view details)

Uploaded Python 3

File details

Details for the file marx_ai-0.1.2.tar.gz.

File metadata

  • Download URL: marx_ai-0.1.2.tar.gz
  • Upload date:
  • Size: 41.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for marx_ai-0.1.2.tar.gz
Algorithm Hash digest
SHA256 dece7ed5d53bd00f36cfbbb7ac043b6a5d953a83c5dffa1c64e46943a2ed3f78
MD5 0ca0da182227890bce248be333862152
BLAKE2b-256 0dcb95bcd29e010ac2459539b6995a9a4d42708bf2d68067b9de74bb3f7bfa1b

See more details on using hashes here.

File details

Details for the file marx_ai-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: marx_ai-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 33.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for marx_ai-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 a733262f3882f69ec54028a2237ddc9eeff686d575df7f8f6fb2205952aba8c1
MD5 47ee28ad4d64eecce3ec84d7a848b01b
BLAKE2b-256 65354ddddd487a9ed835c716bfa578ac71da3c8d0a58c378b88a6deeb7bcfdc6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page