> ## Documentation Index
> Fetch the complete documentation index at: https://codspeed.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> Get started with CodSpeed and performance testing in a few minutes

# Quickstart

export const CIWorkflow = ({minimal = false, enableWorkflowDispatch = true, runsOn = "ubuntu-latest", highlight = [], mode, modes, submodules = false, preSteps = [], buildSteps = ["# ...", "# Setup your environment here:", "#  - Configure your Python/Rust/Node version", "#  - Install your dependencies", "#  - Build your benchmarks (if using a compiled language)", "# ..."], benchmarkCommand = ["<Insert your benchmark command here>"], jobName = "Run benchmarks", env = {}}) => {
  const modeList = modes || (mode ? [mode] : undefined);
  if (!modeList || modeList.length === 0) {
    throw new Error("mode or modes is required");
  }
  const indent = (lines, depth) => {
    const reindentedLines = lines.map(l => l.length === 0 ? l : (" ").repeat(depth) + l);
    return reindentedLines.join("\n");
  };
  const workflowDispatchSection = enableWorkflowDispatch ? "  # `workflow_dispatch` allows CodSpeed to trigger backtest\n" + "  # performance analysis in order to generate initial data.\n" + "  workflow_dispatch:\n" : "";
  let yaml = "";
  if (!minimal) {
    yaml += `
name: CodSpeed Benchmarks

on:
  push:
    branches:
      - "main" # or "master"
  pull_request:
`;
    yaml += workflowDispatchSection;
  }
  yaml += `
jobs:
  benchmarks:
    name: ${jobName}
    runs-on: ${runsOn}`;
  if (!minimal) {
    yaml += `
    permissions: # optional for public repositories
      contents: read # required for actions/checkout
      id-token: write # required for OIDC authentication with CodSpeed`;
  }
  if (preSteps.length > 0) yaml += "\n" + indent(preSteps, 4);
  yaml += `
    steps:
      - uses: actions/checkout@v5`;
  if (submodules) {
    const value = typeof submodules === "string" ? submodules : "true";
    yaml += `\n        with:\n          submodules: ${value}`;
  }
  yaml += "\n" + indent(buildSteps, 6);
  const modeValue = modeList.join(",");
  yaml += `
      - name: Run the benchmarks
        uses: CodSpeedHQ/action@v4
        with:
          mode: ${modeValue}`;
  if (benchmarkCommand.length > 0) {
    const indentedBenchCommand = benchmarkCommand.length > 1 ? benchmarkCommand[0] + "\n" + indent(benchmarkCommand.slice(1), 12) : benchmarkCommand;
    const runLine = indent(["run: "], 10) + indentedBenchCommand;
    yaml += `\n${runLine}`;
  }
  const envEntries = Object.entries(env);
  if (envEntries.length > 0) {
    const envLines = ["env:", ...envEntries.map(([k, v]) => `  ${k}: ${v}`)];
    yaml += "\n" + indent(envLines, 8);
  }
  return <CodeBlock language="yaml" highlight={JSON.stringify(highlight)} {...minimal || ({
    filename: ".github/workflows/codspeed.yml",
    icon: "github"
  })}>
      {yaml}
    </CodeBlock>;
};

CodSpeed measures your code performance locally and in your CI/CD pipeline, so
you can catch regressions before they ship and optimize your critical code
paths. Learn more about [how CodSpeed works](/what-is-codspeed).

This guide walks you through
[connecting your repository](#connect-your-repository) and then
[setting up CodSpeed](#setup).

## Connect your Repository

1. [Login on CodSpeed](https://app.codspeed.io/login)

2. Go to [settings](https://app.codspeed.io/settings) and install the CodSpeed
   GitHub App by clicking on the "Import" button.

   <img src="https://mintcdn.com/codspeed/jKaxX6yy-Kzw1C-0/assets/add-new-repository.png?fit=max&auto=format&n=jKaxX6yy-Kzw1C-0&q=85&s=84fb767d81b990e9ba590bf2a8adc0c8" className="rounded-xl w-full max-w-lg mx-auto" alt="Adding a new repository from the settings page" width="1380" height="864" data-path="assets/add-new-repository.png" />

3. Select the organization or the user and add the repositories you want to use
   with CodSpeed:

   <img src="https://mintcdn.com/codspeed/jKaxX6yy-Kzw1C-0/assets/select-organization.png?fit=max&auto=format&n=jKaxX6yy-Kzw1C-0&q=85&s=04ad62074c1d5b91f6f90748cf3067f2" alt="Github App organization selection" className="rounded-xl w-full max-w-sm mx-auto" width="1232" height="906" data-path="assets/select-organization.png" />

4. After connecting your repository, you can proceed to the [setup](#setup) to
   start tracking performance.

## Setup

In the [CodSpeed settings](https://app.codspeed.io/settings), configure a
repository by clicking on the "Setup" button:

<img src="https://mintcdn.com/codspeed/SwdNrtJu0iSVsYr5/assets/github-connect-repo.png?fit=max&auto=format&n=SwdNrtJu0iSVsYr5&q=85&s=291bd83ddc1141ab0d49028e4b4da39c" className="rounded-xl w-full max-w-lg mx-auto" alt="Repository Setup button" width="4074" height="1672" data-path="assets/github-connect-repo.png" />

### Automated setup

<Tip>
  The [CodSpeed Wizard](/ai/wizard) analyzes your repository, configures
  benchmarks, generates a CI workflow, and opens a pull request — all
  automatically. No manual configuration required.
</Tip>

1. From the repository setup screen, click **Start AI Setup** to let the Wizard
   handle the configuration:

   <img src="https://mintcdn.com/codspeed/GE_LrYDPyn_qQoG5/assets/wizard-ai-setup.png?fit=max&auto=format&n=GE_LrYDPyn_qQoG5&q=85&s=4bc6c5420b3a1e64fdcae8ab04eb5d9f" alt="The setup modal showing AI Setup and Manual Setup options, with the Start AI Setup button highlighted" className="w-full max-w-lg mx-auto" width="1119" height="870" data-path="assets/wizard-ai-setup.png" />

2. The Wizard analyzes your repository and configures it:

   <img src="https://mintcdn.com/codspeed/GE_LrYDPyn_qQoG5/assets/wizard-in-progress.png?fit=max&auto=format&n=GE_LrYDPyn_qQoG5&q=85&s=70dabc708d7debde939b371466b81f6d" alt="The setup modal showing AI Setup and Manual Setup options, with the Start AI Setup button highlighted" className="w-full max-w-lg mx-auto" width="1344" height="720" data-path="assets/wizard-in-progress.png" />

3. The Wizard opens a setup **pull request**:
   <img src="https://mintcdn.com/codspeed/jKaxX6yy-Kzw1C-0/assets/quickstart-new-installation-pr.png?fit=max&auto=format&n=jKaxX6yy-Kzw1C-0&q=85&s=039a17923b6efd4dea35bb846593382e" className="rounded-xl w-full max-w-lg mx-auto" alt="Pull Request Result on Installation" width="1690" height="822" data-path="assets/quickstart-new-installation-pr.png" />

4. Review and merge the pull request to complete setup.

#### How it works

The Wizard handles the full setup process automatically:

1. **Detects existing benchmarks**: finds and configures your benchmarks in the
   language and framework you're already using.
2. **Creates benchmarks if needed**: generates appropriate benchmark files when
   none exist in the repository.
3. **Generates CI workflows**: creates optimized GitHub Actions or GitLab CI
   configurations tailored to your setup.
4. **Opens a pull request**: submits all changes for your review before anything
   is merged.

### Manual setup

If you prefer to configure CodSpeed yourself, follow the steps below. This
example uses a Python repository with `pytest`.

#### Create performance tests

1. Install the CodSpeed plugin for `pytest`:

   ```sh theme={null}
   pip install pytest-codspeed
   ```

2. Write a performance test using the `@pytest.mark.benchmark` marker:

   ```python tests/test_sum_squares.py highlight={12} icon="python" theme={null}
   import pytest

   def sum_squares(arr):
       """Sum the squares of the numbers in an array."""
       total = 0
       for x in arr:
           total += x * x
       return total

   # Your tests can also be benchmarks
   @pytest.mark.benchmark
   def test_sum_squares():
       assert sum_squares(range(1000)) == 332833500
   ```

3. Run your performance tests locally: {" "}

   ```shellsession title=terminal icon="square-terminal" theme={null}
   $ pytest tests/ --codspeed
   ============================= test session starts ====================
   platform darwin -- Python 3.13.0, pytest-7.4.4, pluggy-1.5.0
   codspeed: 3.0.0 (enabled, mode: walltime, timer_resolution: 41.7ns)
   rootdir: /home/user/codspeed-test, configfile: pytest.ini
   plugins: codspeed-3.0.0
   collected 1 items

   tests/test_sum_squares.py .                                    [ 100%]

                            Benchmark Results
   ┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━┓
   ┃     Benchmark  ┃ Time (best) ┃ Rel. StdDev ┃ Run time ┃ Iters  ┃
   ┣━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━╋━━━━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━┫
   ┃test_sum_squares┃     1,873ns ┃        4.8% ┃    3.00s ┃ 66,930 ┃
   ┗━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━┻━━━━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━┛
   =============================== 1 benchmarked ========================
   =============================== 1 passed in 4.12s ====================
   ```

   Your first performance test is ready. Next, track it in CI with CodSpeed.

#### Run the tests in your CI

1. Create a new GitHub Actions workflow file to run your benchmarks:

   <CIWorkflow
     enableWorkflowDispatch={false}
     jobName="Run benchmarks"
     buildSteps={[
   `- name: Setup Python`,
   `  uses: actions/setup-python@v6`,
   `  with:`,
   `    python-version: "3.13"`,
   `- name: Install dependencies`,
   `  run: pip install pytest pytest-codspeed`,
   ]}
     benchmarkCommand={["pytest tests/ --codspeed"]}
     mode="simulation"
   />

2. Create a Pull Request installing the workflow to the repository and wait for
   the report in the comments:

   <img src="https://mintcdn.com/codspeed/jKaxX6yy-Kzw1C-0/assets/quickstart-new-installation-pr.png?fit=max&auto=format&n=jKaxX6yy-Kzw1C-0&q=85&s=039a17923b6efd4dea35bb846593382e" className="rounded-xl w-full max-w-lg mx-auto" alt="Pull Request Result on Installation" width="1690" height="822" data-path="assets/quickstart-new-installation-pr.png" />

3. Merge it and congrats, CodSpeed is installed!

#### Introduce a performance regression

1. Let's change the implementation of the `sum_squares` with a more concise and
   elegant one:

   ```python tests/test_sum_squares.py icon="python" theme={null}
   def sum_squares(arr):
       """Sum the squares of the numbers in an array."""
       total = 0 # [!code --:4]
       for x in arr:
           total += x * x
       return total
       return sum(map(lambda x: x**2, arr)) # [!code ++]
   ```

2. Open a Pull Request and wait for the CodSpeed report:

<Frame caption="Pull Request Performance Report showing the performance regression">
  <img src="https://mintcdn.com/codspeed/jKaxX6yy-Kzw1C-0/assets/quickstart-regression-pr.png?fit=max&auto=format&n=jKaxX6yy-Kzw1C-0&q=85&s=7e5b2928d21552a5ec8e27e859448bbf" alt="Pull Request Regression Result" className="w-full max-w-lg mx-auto" width="1736" height="1058" data-path="assets/quickstart-regression-pr.png" />
</Frame>

Before merging, the report shows this new implementation is slower.

<Frame caption="Pull Request Checks failing because of the performance regression">
  <img src="https://mintcdn.com/codspeed/q5Q3QnyKsjTld2tv/assets/quickstart-regression-checks.png?fit=max&auto=format&n=q5Q3QnyKsjTld2tv&q=85&s=cafac36f9a791d06187e998b6ee8d6d7" alt="Pull Request Checks failing because of the performance regression" className="w-full max-w-lg mx-auto" width="831" height="184" data-path="assets/quickstart-regression-checks.png" />
</Frame>

Merging it would have introduced a performance regression, but CodSpeed caught it before it shipped.

<Tip>
  This behavior can be enforced by configuring [performance
  checks](/features/performance-checks/).
</Tip>

## Next Steps

<Columns cols={2}>
  <Card title="What is CodSpeed?" href="/what-is-codspeed" icon="lightbulb">
    Learn how CodSpeed works
  </Card>

  <Card title="pytest-codspeed documentation" icon="code" href="/benchmarks/python">
    Learn more about how to create performance tests with pytest-codspeed
  </Card>

  <Card title="Explore the Performance Metrics" href="/features/understanding-the-metrics/" icon="chart-line">
    Understand the performance metrics generated by CodSpeed
  </Card>

  <Card title="Enforce Performance Checks" href="/features/performance-checks/" icon="shield-check">
    Make sure you or team members never merge unexpected performance
    regressions.
  </Card>
</Columns>
