---
title: "Configuration introduction"
description: "Get started with the CircleCI config.yml file by using the shell, running code from your repository, creating workflows, and adding a manual approval."
platform: "Cloud, Server"
doc_version: "Server"
last_updated: "2026-10-15"
---

> For current CircleCI product defaults, deprecated patterns, and Cloud/Server differences, see [AGENTS.md](https://circleci.com/docs/AGENTS.md).
>
> For the complete documentation index and site structure, see [llms.txt](https://circleci.com/docs/llms.txt).

# Configuration introduction

This guide gets you started with the CircleCI `config.yml` file.

## Getting started with CircleCI config

This guide covers the following topics:

*   How CircleCI finds and runs `config.yml`.
    
*   How you can use shell commands to perform actions.
    
*   How `config.yml` interacts with your code.
    
*   How to trigger a build.
    
*   How to use Docker containers to run your jobs in a specific environment.
    
*   How to use workflows to orchestrate your build.
    
*   How to add approval steps to your workflow.
    

CircleCI believes in **configuration as code**. The entire delivery process from build to deploy is orchestrated through YAML configuration files. A common pattern is to name your configuration file `config.yml` and store it in a folder called `.circleci` at the top of your repository project. See the [Introduction to YAML Configurations](https://circleci.com/docs/guides/server/getting-started/introduction-to-yaml-configurations/) page for guidance on the basics.

## Prerequisites

*   An account on your CircleCI Server instance.
    
*   A code repository you want to build on CircleCI.
    
*   Follow the [Set Up a Project](https://circleci.com/docs/guides/server/getting-started/create-project/#set-up-a-project) steps to connect your repository to CircleCI. You can then use the examples below to configure a basic pipeline using any execution environment.
    

## Part 1: Using the shell

CircleCI provides an on-demand shell to run commands. In this first example, you will set up a build and execute a shell command.

1.  Once you have created or set up your project in CircleCI, go to the `.circleci/config.yml` file and replace its contents with the following code:
    
    **Using Docker?** Authenticating Docker pulls from image registries is recommended when using the Docker execution environment. Authenticated pulls allow access to private Docker images, and may also grant higher rate limits, depending on your registry provider. For further information, see [Using Docker Authenticated Pulls](https://circleci.com/docs/guides/execute/private-images/).
    
    ```yaml
    version: 2.1
    jobs:
      build:
        docker:
          - image: alpine:3.15
        steps:
          - run:
              name: The First Step
              command: |
                echo 'Hello World!'
                echo 'This is the delivery pipeline'
    ```
    
    The following commentary describes what occurs in each line of the sample code:
    
    *   **Line 1:** This indicates the version of the CircleCI platform you are using. `2.1` is the most recent version.
        
    *   **Line 2:** The `jobs` level contains a collection of children, representing your jobs. You specify the names for these jobs, for example, _build_, _test_, _deploy_.
        
    *   **Line 3:** `build` is the first child in the `jobs` collection. In this example, `build` is also the only job.
        
    *   **Line 4:** This specifies that you are using a Docker image for the container where your job’s commands are run.
        
    *   **Line 5:** This is the Docker image. The example shows `alpine:3.15`, a minimal image based on Alpine Linux.
        
        As mentioned in the note above the sample code, you may optionally supply your Docker credentials when using a Docker executor.
        
    *   **Line 6:** The `steps` collection is a list of `run` directives.
        
    *   **Line 7:** Each `run` directive is executed in the order in which it is declared.
        
    *   **Line 8:** The `name` attribute provides useful information when returning warnings, errors, and output. It is helpful if the `name` is meaningful to you as an action within your build process.
        
    *   **Line 9:** The `command` attribute is a list of shell commands that you want to execute. The initial pipe, `|`, indicates there will be multiple lines of shell commands.
        
    *   **Line 10:** Prints `Hello World!` in your build shell.
        
    *   **Line 11:** Prints `This is the delivery pipeline`.
        
    
2.  Commit your `config.yml` file (and push, if you are working remotely).
    
3.  A new pipeline is triggered in CircleCI. You can see the output in the CircleCI web app. A green tick denotes a successful pipeline. A red exclamation mark alerts you to a failure. Click on the job for more details. You can see your step - The First Step - along with the output of the commands.
    

Although the `config.yml` syntax itself is straightforward, the indentation is more complicated. Incorrect indentation is the most common error. If you are experiencing problems with this example, check your indentation carefully, or copy and paste the sample code.

## Part 2: Using code from your repository

CircleCI provides several commands to simplify complex actions. In this example, you will use the `checkout` command. This command fetches the code from your git repository. Once you have retrieved that code, you can work with it in subsequent steps.

If you have not done so already, create a `.circleci` directory in your project, add a `config.yml` file, and type or paste the code from the example below.

If you already have a `config.yml` file from the example above, here are the changes you need to make:

*   On Line 5, change the image to `cimg/base:2021.04`.
    
*   On Line 7, add a `checkout` command.
    
*   Add another run step (lines 13-17) at the end.
    

Make sure you observe the indentation.

```yaml
version: 2.1
jobs:
  build:
    docker:
      - image: cimg/base:2021.04
    steps:
      - checkout
      - run:
          name: The First Step
          command: |
            echo 'Hello World!'
            echo 'This is the delivery pipeline'
      - run:
          name: The Second Step
          command: |
            ls -al
            echo '^^^The files in your repo^^^'
```

These two small changes have significantly increased the functionality of your config file:

*   **Line 5:** This line now specifies a Docker image that supports git. `cimg/base:2021.04` is a small Ubuntu-based image for running basic jobs.
    
*   **Line 7:** The `checkout` command fetches the code from your git repository.
    
*   **Lines 13-17:** This second step in the `build` job is listing (using `ls -al`) the contents of the repository that has been checked out. You can now perform further actions on this repository.
    

As before, commit and push your updated `config.yml` file.

You can now see some additional steps on the CircleCI dashboard:

*   **Checkout code** has cloned the code from your git repository.
    
*   **The Second Step** has listed the files found in your git repository.
    

## Part 3: Using different environments and creating workflows

In Parts 1 and 2, you ran your job in basic Linux-based Docker containers.

With CircleCI, you can run different jobs in different execution environments, such as virtual machines or Docker containers. By changing the Docker image, you can quickly upgrade your environment version or change languages.

In this part, you will create additional jobs and run them using different Docker images.

If you have not done so already, create a `.circleci` directory in your project, add a `config.yml` file, and type or paste the code from the example below.

```yaml
version: 2.1
jobs:
  # running commands on a basic image
  Hello-World:
    docker:
      - image: cimg/base:2026.03
    steps:
      - run:
          name: Saying Hello
          command: |
            echo 'Hello World!'
            echo 'This is the delivery pipeline'
  # fetching code from the repo
  Fetch-Code:
    docker:
      - image: cimg/base:2026.03
    steps:
      - checkout
      - run:
          name: Getting the Code
          command: |
            ls -al
            echo '^^^Your repo files^^^'
  # running a node container
  Using-Node:
    docker:
      - image: cimg/node:25.8.1
    steps:
      - run:
          name: Running the Node Container
          command: |
            node -v
workflows:
  Example-Workflow:
    jobs:
      - Hello-World
      - Fetch-Code:
          requires:
            - Hello-World
      - Using-Node:
          requires:
            - Fetch-Code
```

This example is more complicated than the others, but it introduces several important concepts. Parts 1 and 2 included just one job called _build_, which contained several steps. This example includes three jobs. By separating those steps into jobs, you can run each of them in a different environment.

The following commentary describes what occurs in each line of the sample code:

*   **Line 3:** You can add comments to your config.yml file by preceding them with the # (hash) sign.
    
*   **Lines 4-12:** The first job is _Hello-World_. As in Part 1, it runs two commands in a basic image.
    
*   **Line 14:** The second job is _Fetch-Code_. It is indented to align with the _Hello-World_ job.
    
*   **Lines 15-16:** The _Fetch-Code_ job uses a basic git-compatible image.
    
*   **Lines 17-23:** This code is repeated from Part 2, but now it is a separate job.
    
*   **Line 25:** The third job is _Using-Node_.
    
*   **Lines 26-27:** This _Using-Node_ job uses a Docker image called `cimg/node:25.8.1`. This image contains version 25.8.1 of Node, along with a browser and other useful tools.
    
*   **Lines 28-32:** As in the previous jobs, there is a _run_ step. This time, the command `node -v` prints the version of Node running in the container.
    
*   **Lines 33-34:** This line creates a workflow called _Example-Workflow_. Workflows define a list of jobs and their run order.
    
*   **Lines 35-36:** These lines specify the first job, _Hello-World_.
    
*   **Lines 37-39:** The syntax for the _Fetch-Code_ job is slightly different. The job name is followed by a `requires:`, then a _requires_ statement. This line specifies that the _Hello-World_ job must run successfully before the _Fetch-Code_ job is executed.
    
*   **Lines 40-42:** The final job is _Using-Node_. As before, this job requires the successful completion of the previous job, _Fetch-Code_.
    

As before, commit and push your updated `config.yml` file.

In CircleCI, your pipeline will look different. Your workflow is now called _Example-Workflow_ and you have three jobs, rather than just one.

If you click on the _Using-Node_ job and then the _Running the Node Container_ step, you can see that the command `node -v` has printed the version of Node.

In this example, you have:

*   Added comments to document your jobs.
    
*   Created multiple jobs to run in different Docker containers.
    
*   Created a workflow to define the order in which your jobs run.
    
*   Introduced some logic to ensure that the previous job must complete successfully before the next job is executed.
    

To increase your understanding, experiment with other [CircleCI Images](https://circleci.com/docs/guides/server/execute/circleci-images/), or add some more jobs to your workflow.

## Part 4: Adding a manual approval

The CircleCI workflow model is based on the orchestration of preceding jobs. As you saw in Part 3, the `requires` statement specifies that a job runs only if the previous job has been successfully executed.

In Part 3, an event triggering the pipeline caused the `Hello-World` job to run immediately. The remaining jobs ran automatically, once `Hello-World` had completed successfully.

In this part, you will create a manual approval stage. This means subsequent jobs are executed only after you have approved the next step in the CircleCI app.

If you have not done so already, create a `.circleci` directory in your project, add a `config.yml` file, and type or paste the code from the example below:

```yaml
version: 2.1
jobs:
  # running commands on a basic image
  Hello-World:
    docker:
      - image: alpine:3.23.3
    steps:
      - run:
          name: Saying Hello
          command: |
            echo 'Hello World!'
            echo 'This is the delivery pipeline'
  # fetching code from the repo
  Fetch-Code:
    docker:
      - image: cimg/base:2026.03
    steps:
      - checkout
      - run:
          name: Getting the Code
          command: |
            ls -al
            echo '^^^Your repo files^^^'
  # running a node container
  Using-Node:
    docker:
      - image: cimg/node:25.8.1
    steps:
      - run:
          name: Running the Node Container
          command: |
            node -v
  Now-Complete:
    docker:
      - image: alpine:3.23.3
    steps:
      - run:
          name: Approval Complete
          command: |
            echo 'The work is now complete.'

workflows:
  Example-Workflow:
    jobs:
      - Hello-World
      - Fetch-Code:
          requires:
            - Hello-World
      - Using-Node:
          requires:
            - Fetch-Code
      - Hold-for-Approval:
          type: approval
          requires:
            - Using-Node
            - Fetch-Code
      - Now-Complete:
          requires:
            - Hold-for-Approval
```

Most of this code will look familiar to you, with a couple of important points:

*   **Lines 52-56**: This creates a new job called _Hold-for-Approval_. The `type` specifies this is an _approval_, so you are required to manually approve this job in CircleCI. An approval job is useful if you want to see whether the previous jobs have been executed as expected. For example, you can check that a website looks correct on a test server before making it live. Or you might want a human to perform checks before you execute any expensive jobs.
    
*   **Lines 57-59**: This final job - _Now-Complete_ - `requires` the successful completion of _Hold-for-Approval_, so it will execute only once you have approved that previous job in CircleCI.
    

As before, commit and push your updated `config.yml` file.

If you look at your pipeline in CircleCI, you will see a purple status badge of **Needs Approval**.

To approve the job, select the thumbs up icon to the right of the _Hold-for-Approval_ job in the _Actions_ column. In the pop-up message, click the blue **Approve** button.

Now you will see a tick in the Actions column and your jobs will complete.

Select the _Now-Complete_ job, then the _Approval Complete_ step. You can see the output of your command: `The work is now complete`.

If you encounter errors, the problem is likely to be caused by incorrect indentation. The [CircleCI Configuration Editor](https://circleci.com/docs/guides/server/getting-started/config-editor/) validates your syntax, provides autocomplete suggestions, and offers tips.

In this example, you have:

*   Introduced some additional logic to control your workflow.
    
*   Implemented the `approval` job type to require a manual approval within your workflow.
    

Using what you have learned above, you are ready to create some powerful pipelines.

## VS Code extension

If you use VS Code, you might find the official [CircleCI Extension](https://circleci.com/docs/guides/server/toolkit/vs-code-extension-overview/) useful when writing, editing, navigating and troubleshooting your YAML config files.

The extension provides real-time syntax highlighting and validation, assisted navigation through go-to-definition and go-to-reference commands, usage hints, and autocomplete suggestions.

> **Image:** Screenshot showing the definition available on hover

Figure 1. Screenshot showing the definition available on hover

The CircleCI VS Code extension is available to download on the [VS Code marketplace.](https://marketplace.visualstudio.com/items?itemName=circleci.circleci)

## See also

*   [Configuring CircleCI](https://circleci.com/docs/reference/configuration-reference/)
    
*   [Executors and Images](https://circleci.com/docs/guides/server/execute/executor-intro/)
    
*   [Using Workflows to Orchestrate Jobs](https://circleci.com/docs/guides/server/orchestrate/workflows/)