CLI Reference
Installation
Section titled “Installation”curl -fsSL https://app.gaffer.sh/install.sh | shInstalls the gaffer binary to ~/.local/bin. Supports Linux (x86_64, aarch64) and macOS (Apple Silicon, Intel). For a guided walkthrough, see the Getting Started guide.
gaffer test
Section titled “gaffer test”Run a test command and analyze results.
gaffer test -- npm testgaffer test -- pytest -xgaffer test -- go test ./...gaffer test -- cargo test| Flag | Env var | Description |
|---|---|---|
--token <token> | GAFFER_TOKEN | API token for cloud sync |
--report <path> / -r <path> | — | Report file path(s) to parse (repeatable) |
--root <dir> | — | Project root directory (default: .) |
--format <human|json> | — | Output format (default: human) |
--show-errors | — | Show full error messages, stack traces, and context files for failed tests |
--compare <branch> | — | Compare against the latest run on a branch (e.g. --compare=main) |
--api-url <url> | GAFFER_API_URL | Override API endpoint |
Behavior
Section titled “Behavior”- Runs your command as a child process, passing through stdout/stderr
- Discovers report files via glob patterns (config or defaults)
- Parses test results and coverage reports
- Computes health score, flaky tests, failure clusters, duration analysis
- Prints enriched summary to stderr
- Syncs results to cloud (if token configured)
- Exits with the child process’s exit code
Example output
Section titled “Example output”gaffer 40 passed 2 failed 3 skipped 12.4sHealth: 87 (good) ^ Slow: p95 245.3msFlaky: 2 tests src/auth.test.ts > login — 40% flip rate (4/10 runs) src/api.test.ts > timeout handler — 20% flip rate (2/10 runs)Clusters: 1 pattern (3 tests) "Connection refused" — 3 testsCoverage: 78.5% lines (1234/1572)Synced: 1 run uploadedBranch comparison
Section titled “Branch comparison”Compare the current run against a baseline branch:
gaffer test --compare=main -- npm testvs main: 2 new failures, 1 fixed, 3 pre-existing pass rate -5.0% duration +1.2s NEW src/auth.test.ts > login > OAuth redirect NEW src/billing.test.ts > charge card FIX src/api.test.ts > timeout handlerJSON output
Section titled “JSON output”Use --format=json to get machine-readable output on stdout:
gaffer test --format=json -- npm test | jq .health.scoregaffer init
Section titled “gaffer init”Interactive project setup.
gaffer initSteps:
- Detects test frameworks (Vitest, Playwright, Jest, pytest, Go, RSpec)
- Shows reporter setup instructions for each detected framework
- Optionally authenticates via browser (creates API token)
- Writes
.gaffer/config.toml - Adds
.gaffer/to.gitignore
gaffer query
Section titled “gaffer query”Query local test intelligence without running tests. Output is JSON by default — use --pretty for human-readable. AI agents can access the same data via the MCP server.
gaffer query health
Section titled “gaffer query health”Health score, trend, and label.
gaffer query healthgaffer query health --prettygaffer query health | jq .scoregaffer query flaky
Section titled “gaffer query flaky”Flaky tests ranked by composite score.
gaffer query flakygaffer query flaky | jq '.[].test_name'gaffer query slowest
Section titled “gaffer query slowest”Top N slowest tests by duration.
gaffer query slowestgaffer query slowest --limit 5gaffer query runs
Section titled “gaffer query runs”Recent test runs with pass/fail counts.
gaffer query runsgaffer query runs --limit 5gaffer query history "<test>"
Section titled “gaffer query history "<test>"”Pass/fail history for a specific test (name matched with LIKE).
gaffer query history "login"gaffer query history "auth > login" --limit 10gaffer query failures "<pattern>"
Section titled “gaffer query failures "<pattern>"”Search failures across runs by test name or error message.
gaffer query failures "timeout"gaffer query failures "connection refused" --limit 10gaffer sync
Section titled “gaffer sync”Force-sync pending uploads. Use when a previous gaffer test run was interrupted before syncing, or to retry failed uploads. To upload reports without the CLI, see the Upload API.
gaffer syncgaffer sync --token gaf_xxxConfiguration
Section titled “Configuration”Config file: .gaffer/config.toml (or gaffer.toml at project root)
[project]token = "gaf_..."api_url = "https://app.gaffer.sh"
[test]report_patterns = [ "**/.gaffer/reports/**/*.xml", "**/.gaffer/reports/**/*.json", "**/junit*.xml", "**/test-results/**/*.xml", "**/test-reports/**/*.xml", "**/ctrf/**/*.json", "**/ctrf-report.json", "**/coverage/lcov.info", "**/lcov.info",]Resolution order: CLI flags > environment variables > config file > defaults.
Config discovery: Walks up from the working directory looking for .gaffer/config.toml or gaffer.toml. The directory containing the config becomes the project root.
Environment variables
Section titled “Environment variables”| Variable | Purpose |
|---|---|
GAFFER_TOKEN | API token for cloud sync (overridden by --token) |
GAFFER_API_URL | API endpoint URL (overridden by --api-url) |
Default report patterns
Section titled “Default report patterns”When no --report flag or report_patterns config is set, Gaffer auto-discovers:
**/.gaffer/reports/**/*.xml— Gaffer’s own report directory**/.gaffer/reports/**/*.json— Gaffer’s own report directory**/junit*.xml— JUnit XML reports**/test-results/**/*.xml— Common test result directories**/test-reports/**/*.xml— Common test report directories**/ctrf/**/*.json— CTRF JSON reports**/ctrf-report.json— Default CTRF output**/coverage/lcov.info— Default coverage output**/lcov.info— Root-level coverage