{"meta":{"title":"Workflow commands for GitHub Actions","intro":"You can use workflow commands when running shell commands in a workflow or in an action's code.","product":"GitHub Actions","breadcrumbs":[{"href":"/en/actions","title":"GitHub Actions"},{"href":"/en/actions/reference","title":"Reference"},{"href":"/en/actions/reference/workflows-and-actions","title":"Workflows and actions"},{"href":"/en/actions/reference/workflows-and-actions/workflow-commands","title":"Workflow commands"}],"documentType":"article"},"body":"# Workflow commands for GitHub Actions\n\nYou can use workflow commands when running shell commands in a workflow or in an action's code.\n\n## About workflow commands\n\nActions can communicate with the runner machine to set environment variables, output values used by other actions, add debug messages to the output logs, and other tasks.\n\nMost workflow commands use the `echo` command in a specific format, while others are invoked by writing to a file. For more information, see [Environment files](#environment-files).\n\n### Example of a workflow command\n\n<div class=\"ghd-tool bash\">\n\n```bash copy\necho \"::workflow-command parameter1={data},parameter2={data}::{command value}\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```powershell copy\nWrite-Output \"::workflow-command parameter1={data},parameter2={data}::{command value}\"\n```\n\n</div>\n\n> \\[!NOTE]\n> Workflow command and parameter names are case insensitive.\n\n> \\[!WARNING]\n> If you are using Command Prompt, omit double quote characters (`\"`) when using workflow commands.\n\n## Using workflow commands to access toolkit functions\n\nThe [actions/toolkit](https://github.com/actions/toolkit) includes a number of functions that can be executed as workflow commands. Use the `::` syntax to run the workflow commands within your YAML file; these commands are then sent to the runner over `stdout`.\n\nFor example, instead of using code to create an error annotation, as below:\n\n```javascript copy\ncore.error('Missing semicolon', {file: 'app.js', startLine: 1})\n```\n\n### Example: Creating an annotation for an error\n\nYou can use the `error` command in your workflow to create the same error annotation:\n\n<div class=\"ghd-tool bash\">\n\n```yaml copy\n      - name: Create annotation for build error\n        run: echo \"::error file=app.js,line=1::Missing semicolon\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```yaml copy\n      - name: Create annotation for build error\n        run: Write-Output \"::error file=app.js,line=1::Missing semicolon\"\n```\n\n</div>\n\nThe following table shows which toolkit functions are available within a workflow:\n\n| Toolkit function      | Equivalent workflow command                             |\n| --------------------- | ------------------------------------------------------- |\n| `core.addPath`        | Accessible using environment file `GITHUB_PATH`         |\n| `core.debug`          | `debug`                                                 |\n| `core.notice`         | `notice`                                                |\n| `core.error`          | `error`                                                 |\n| `core.endGroup`       | `endgroup`                                              |\n| `core.exportVariable` | Accessible using environment file `GITHUB_ENV`          |\n| `core.getInput`       | Accessible using environment variable `INPUT_{NAME}`    |\n| `core.getState`       | Accessible using environment variable `STATE_{NAME}`    |\n| `core.isDebug`        | Accessible using environment variable `RUNNER_DEBUG`    |\n| `core.summary`        | Accessible using environment file `GITHUB_STEP_SUMMARY` |\n| `core.saveState`      | Accessible using environment file `GITHUB_STATE`        |\n| `core.setCommandEcho` | `echo`                                                  |\n| `core.setFailed`      | Used as a shortcut for `::error` and `exit 1`           |\n| `core.setOutput`      | Accessible using environment file `GITHUB_OUTPUT`       |\n| `core.setSecret`      | `add-mask`                                              |\n| `core.startGroup`     | `group`                                                 |\n| `core.warning`        | `warning`                                               |\n\n## Setting a debug message\n\nPrints a debug message to the log. You must create a secret named `ACTIONS_STEP_DEBUG` with the value `true` to see the debug messages set by this command in the log. For more information, see [Enabling debug logging](/en/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging).\n\n```text copy\n::debug::{message}\n```\n\n### Example: Setting a debug message\n\n<div class=\"ghd-tool bash\">\n\n```bash copy\necho \"::debug::Set the Octocat variable\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```powershell copy\nWrite-Output \"::debug::Set the Octocat variable\"\n```\n\n</div>\n\n## Setting a notice message\n\nCreates a notice message and prints the message to the log. This message will create an annotation, which can associate the message with a particular file in your repository. Optionally, your message can specify a position within the file.\n\n```text copy\n::notice file={name},line={line},endLine={endLine},title={title}::{message}\n```\n\n| Parameter   | Value                        | Required | Default   |\n| :---------- | :--------------------------- | :------- | :-------- |\n| `title`     | Custom title                 | No       | None      |\n| `file`      | Filename                     | No       | `.github` |\n| `col`       | Column number, starting at 1 | No       | None      |\n| `endColumn` | End column number            | No       | None      |\n| `line`      | Line number, starting at 1   | No       | `1`       |\n| `endLine`   | End line number              | No       | `1`       |\n\n### Example: Setting a notice message\n\n<div class=\"ghd-tool bash\">\n\n```bash copy\necho \"::notice file=app.js,line=1,col=5,endColumn=7::Missing semicolon\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```powershell copy\nWrite-Output \"::notice file=app.js,line=1,col=5,endColumn=7,title=YOUR-TITLE::Missing semicolon\"\n```\n\n</div>\n\n## Setting a warning message\n\nCreates a warning message and prints the message to the log. This message will create an annotation, which can associate the message with a particular file in your repository. Optionally, your message can specify a position within the file.\n\n```text copy\n::warning file={name},line={line},endLine={endLine},title={title}::{message}\n```\n\n| Parameter   | Value                        | Required | Default   |\n| :---------- | :--------------------------- | :------- | :-------- |\n| `title`     | Custom title                 | No       | None      |\n| `file`      | Filename                     | No       | `.github` |\n| `col`       | Column number, starting at 1 | No       | None      |\n| `endColumn` | End column number            | No       | None      |\n| `line`      | Line number, starting at 1   | No       | `1`       |\n| `endLine`   | End line number              | No       | `1`       |\n\n### Example: Setting a warning message\n\n<div class=\"ghd-tool bash\">\n\n```bash copy\necho \"::warning file=app.js,line=1,col=5,endColumn=7,title=YOUR-TITLE::Missing semicolon\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```powershell copy\nWrite-Output \"::warning file=app.js,line=1,col=5,endColumn=7,title=YOUR-TITLE::Missing semicolon\"\n```\n\n</div>\n\n## Setting an error message\n\nCreates an error message and prints the message to the log. This message will create an annotation, which can associate the message with a particular file in your repository. Optionally, your message can specify a position within the file.\n\n```text copy\n::error file={name},line={line},endLine={endLine},title={title}::{message}\n```\n\n| Parameter   | Value                        | Required | Default   |\n| :---------- | :--------------------------- | :------- | :-------- |\n| `title`     | Custom title                 | No       | None      |\n| `file`      | Filename                     | No       | `.github` |\n| `col`       | Column number, starting at 1 | No       | None      |\n| `endColumn` | End column number            | No       | None      |\n| `line`      | Line number, starting at 1   | No       | `1`       |\n| `endLine`   | End line number              | No       | `1`       |\n\n### Example: Setting an error message\n\n<div class=\"ghd-tool bash\">\n\n```bash copy\necho \"::error file=app.js,line=1,col=5,endColumn=7,title=YOUR-TITLE::Missing semicolon\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```powershell copy\nWrite-Output \"::error file=app.js,line=1,col=5,endColumn=7,title=YOUR-TITLE::Missing semicolon\"\n```\n\n</div>\n\n## Grouping log lines\n\nCreates an expandable group in the log. To create a group, use the `group` command and specify a `title`. Anything you print to the log between the `group` and `endgroup` commands is nested inside an expandable entry in the log.\n\n```text copy\n::group::{title}\n::endgroup::\n```\n\n### Example: Grouping log lines\n\n<div class=\"ghd-tool bash\">\n\n```yaml copy\njobs:\n  bash-example:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Group of log lines\n        run: |\n            echo \"::group::My title\"\n            echo \"Inside group\"\n            echo \"::endgroup::\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```yaml copy\njobs:\n  powershell-example:\n    runs-on: windows-latest\n    steps:\n      - name: Group of log lines\n        run: |\n            Write-Output \"::group::My title\"\n            Write-Output \"Inside group\"\n            Write-Output \"::endgroup::\"\n```\n\n</div>\n\n![Screenshot of the log for the workflow step. The second line, \"My title\", is an expanded group. The next line, \"Inside group\", is indented below.](/assets/images/help/actions/actions-log-group.png)\n\n## Masking a value in a log\n\n```text copy\n::add-mask::{value}\n```\n\nMasking a value prevents a string or variable from being printed in the log. Each masked word separated by whitespace is replaced with the `*` character. You can use an environment variable or string for the mask's `value`. When you mask a value, it is treated as a secret and will be redacted on the runner. For example, after you mask a value, you won't be able to set that value as an output.\n\n### Example: Masking a string\n\nWhen you print `\"Mona The Octocat\"` in the log, you'll see `\"***\"`.\n\n<div class=\"ghd-tool bash\">\n\n```bash copy\necho \"::add-mask::Mona The Octocat\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```powershell copy\nWrite-Output \"::add-mask::Mona The Octocat\"\n```\n\n</div>\n\n> \\[!WARNING]\n> Make sure you register the secret with 'add-mask' before outputting it in the build logs or using it in any other workflow commands.\n\n### Example: Masking an environment variable\n\nWhen you print the variable `MY_NAME` or the value `\"Mona The Octocat\"` in the log, you'll see `\"***\"` instead of `\"Mona The Octocat\"`.\n\n<div class=\"ghd-tool bash\">\n\n```yaml copy\njobs:\n  bash-example:\n    runs-on: ubuntu-latest\n    env:\n      MY_NAME: \"Mona The Octocat\"\n    steps:\n      - name: bash-version\n        run: echo \"::add-mask::$MY_NAME\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```yaml copy\njobs:\n  powershell-example:\n    runs-on: windows-latest\n    env:\n      MY_NAME: \"Mona The Octocat\"\n    steps:\n      - name: powershell-version\n        run: Write-Output \"::add-mask::$env:MY_NAME\"\n```\n\n</div>\n\n### Example: Masking a generated output within a single job\n\nIf you do not need to pass your secret from one job to another job, you can:\n\n1. Generate the secret (without outputting it).\n2. Mask it with `add-mask`.\n3. Use `GITHUB_OUTPUT` to make the secret available to other steps within the job.\n\n<div class=\"ghd-tool bash\">\n\n```yaml copy\non: push\njobs:\n  generate-a-secret-output:\n    runs-on: ubuntu-latest\n    steps:\n      - id: sets-a-secret\n        name: Generate, mask, and output a secret\n        run: |\n          the_secret=$((RANDOM))\n          echo \"::add-mask::$the_secret\"\n          echo \"secret-number=$the_secret\" >> \"$GITHUB_OUTPUT\"\n      - name: Use that secret output (protected by a mask)\n        run: |\n          echo \"the secret number is ${{ steps.sets-a-secret.outputs.secret-number }}\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```yaml copy\non: push\njobs:\n  generate-a-secret-output:\n    runs-on: ubuntu-latest\n    steps:\n      - id: sets-a-secret\n        name: Generate, mask, and output a secret\n        shell: pwsh\n        run: |\n          Set-Variable -Name TheSecret -Value (Get-Random)\n          Write-Output \"::add-mask::$TheSecret\"\n          \"secret-number=$TheSecret\" >> $env:GITHUB_OUTPUT\n      - name: Use that secret output (protected by a mask)\n        shell: pwsh\n        run: |\n          Write-Output \"the secret number is ${{ steps.sets-a-secret.outputs.secret-number }}\"\n```\n\n</div>\n\n### Example: Masking and passing a secret between jobs or workflows\n\nIf you want to pass a masked secret between jobs or workflows, you should store the secret in a store and then retrieve it in the subsequent job or workflow.\n\n#### Setup\n\n1. Set up a secret store to store the secret that you will generate during your workflow. For example, Vault.\n2. Generate a key for reading and writing to that secret store. Store the key as a repository secret. In the following example workflow, the secret name is `SECRET_STORE_CREDENTIALS`. For more information, see [Using secrets in GitHub Actions](/en/actions/security-guides/using-secrets-in-github-actions).\n\n#### Workflow\n\n> \\[!NOTE]\n> This workflow uses an imaginary secret store, `secret-store`, which has imaginary commands `store-secret` and `retrieve-secret`. `some/secret-store@ 27b31702a0e7fc50959f5ad993c78deac1bdfc29` is an imaginary action that installs the `secret-store` application and configures it to connect to an `instance` with `credentials`.\n\n<div class=\"ghd-tool bash\">\n\n```yaml copy\non: push\n\njobs:\n  secret-generator:\n    runs-on: ubuntu-latest\n    outputs:\n      handle: ${{ steps.generate-secret.outputs.handle }}\n    steps:\n    - uses: some/secret-store@27b31702a0e7fc50959f5ad993c78deac1bdfc29\n      with:\n        credentials: ${{ secrets.SECRET_STORE_CREDENTIALS }}\n        instance: ${{ secrets.SECRET_STORE_INSTANCE }}\n    - name: generate secret\n      id: generate-secret\n      shell: bash\n      run: |\n        GENERATED_SECRET=$((RANDOM))\n        echo \"::add-mask::$GENERATED_SECRET\"\n        SECRET_HANDLE=$(secret-store store-secret \"$GENERATED_SECRET\")\n        echo \"handle=$SECRET_HANDLE\" >> \"$GITHUB_OUTPUT\"\n  secret-consumer:\n    runs-on: macos-latest\n    needs: secret-generator\n    steps:\n    - uses: some/secret-store@27b31702a0e7fc50959f5ad993c78deac1bdfc29\n      with:\n        credentials: ${{ secrets.SECRET_STORE_CREDENTIALS }}\n        instance: ${{ secrets.SECRET_STORE_INSTANCE }}\n    - name: use secret\n      shell: bash\n      run: |\n        SECRET_HANDLE=\"${{ needs.secret-generator.outputs.handle }}\"\n        RETRIEVED_SECRET=$(secret-store retrieve-secret \"$SECRET_HANDLE\")\n        echo \"::add-mask::$RETRIEVED_SECRET\"\n        echo \"We retrieved our masked secret: $RETRIEVED_SECRET\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```yaml copy\non: push\n\njobs:\n  secret-generator:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: some/secret-store@27b31702a0e7fc50959f5ad993c78deac1bdfc29\n      with:\n        credentials: ${{ secrets.SECRET_STORE_CREDENTIALS }}\n        instance: ${{ secrets.SECRET_STORE_INSTANCE }}\n    - name: generate secret\n      shell: pwsh\n      run: |\n        Set-Variable -Name Generated_Secret -Value (Get-Random)\n        Write-Output \"::add-mask::$Generated_Secret\"\n        Set-Variable -Name Secret_Handle -Value (Store-Secret \"$Generated_Secret\")\n        \"handle=$Secret_Handle\" >> $env:GITHUB_OUTPUT\n  secret-consumer:\n    runs-on: macos-latest\n    needs: secret-generator\n    steps:\n    - uses: some/secret-store@27b31702a0e7fc50959f5ad993c78deac1bdfc29\n      with:\n        credentials: ${{ secrets.SECRET_STORE_CREDENTIALS }}\n        instance: ${{ secrets.SECRET_STORE_INSTANCE }}\n    - name: use secret\n      shell: pwsh\n      run: |\n        Set-Variable -Name Secret_Handle -Value \"${{ needs.secret-generator.outputs.handle }}\"\n        Set-Variable -Name Retrieved_Secret -Value (Retrieve-Secret \"$Secret_Handle\")\n        echo \"::add-mask::$Retrieved_Secret\"\n        echo \"We retrieved our masked secret: $Retrieved_Secret\"\n```\n\n</div>\n\n## Stopping and starting workflow commands\n\nStops processing any workflow commands. This special command allows you to log anything without accidentally running a workflow command. For example, you could stop logging to output an entire script that has comments.\n\n```text copy\n::stop-commands::{endtoken}\n```\n\nTo stop the processing of workflow commands, pass a unique token to `stop-commands`. To resume processing workflow commands, pass the same token that you used to stop workflow commands.\n\n> \\[!WARNING]\n> Make sure the token you're using is randomly generated and unique for each run.\n\n```text copy\n::{endtoken}::\n```\n\n### Example: Stopping and starting workflow commands\n\n<div class=\"ghd-tool bash\">\n\n```yaml copy\njobs:\n  workflow-command-job:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Disable workflow commands\n        run: |\n          echo '::warning:: This is a warning message, to demonstrate that commands are being processed.'\n          stopMarker=$(uuidgen)\n          echo \"::stop-commands::$stopMarker\"\n          echo '::warning:: This will NOT be rendered as a warning, because stop-commands has been invoked.'\n          echo \"::$stopMarker::\"\n          echo '::warning:: This is a warning again, because stop-commands has been turned off.'\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```yaml copy\njobs:\n  workflow-command-job:\n    runs-on: windows-latest\n    steps:\n      - name: Disable workflow commands\n        run: |\n          Write-Output '::warning:: This is a warning message, to demonstrate that commands are being processed.'\n          $stopMarker = New-Guid\n          Write-Output \"::stop-commands::$stopMarker\"\n          Write-Output '::warning:: This will NOT be rendered as a warning, because stop-commands has been invoked.'\n          Write-Output \"::$stopMarker::\"\n          Write-Output '::warning:: This is a warning again, because stop-commands has been turned off.'\n```\n\n</div>\n\n## Sending values to the pre and post actions\n\nYou can create environment variables for sharing with your workflow's `pre:` or `post:` actions by writing to the file located at `GITHUB_STATE`. For example, you can create a file with the `pre:` action, pass the file location to the `main:` action, and then use the `post:` action to delete the file. Alternatively, you could create a file with the `main:` action, pass the file location to the `post:` action, and also use the `post:` action to delete the file.\n\nIf you have multiple `pre:` or `post:` actions, you can only access the saved value in the action where it was written to `GITHUB_STATE`. For more information on the `post:` action, see [Metadata syntax reference](/en/actions/creating-actions/metadata-syntax-for-github-actions#runspost).\n\nThe `GITHUB_STATE` file is only available within an action. The saved value is stored as an environment value with the `STATE_` prefix.\n\nThis example uses JavaScript to write to the `GITHUB_STATE` file. The resulting environment variable is named `STATE_processID` with the value of `12345`:\n\n```javascript copy\nimport * as fs from 'fs'\nimport * as os from 'os'\n\nfs.appendFileSync(process.env.GITHUB_STATE, `processID=12345${os.EOL}`, {\n  encoding: 'utf8'\n})\n```\n\nThe `STATE_processID` variable is then exclusively available to the cleanup script running under the `main` action. This example runs in `main` and uses JavaScript to display the value assigned to the `STATE_processID` environment variable:\n\n```javascript copy\nconsole.log(\"The running PID from the main action is: \" + process.env.STATE_processID);\n```\n\n## Environment files\n\nDuring the execution of a workflow, the runner generates temporary files that can be used to perform certain actions. The path to these files can be accessed and edited using GitHub's default environment variables. See [Variables reference](/en/actions/reference/variables-reference#default-environment-variables). You will need to use UTF-8 encoding when writing to these files to ensure proper processing of the commands. Multiple commands can be written to the same file, separated by newlines.\nTo use environment variables in a GitHub Action, you create or modify `.env` files using specific GitHub Actions commands.\n\nHere's how:\n\n```yaml copy\nname: Example Workflow for Environment Files\n\non: push\n\njobs:\n  set_and_use_env_vars:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Set environment variable\n        run: echo \"MY_ENV_VAR=myValue\" >> $GITHUB_ENV\n\n      - name: Use environment variable\n        run: |\n          echo \"The value of MY_ENV_VAR is $MY_ENV_VAR\"\n\n```\n\nAnother example would be to use it to store metadata like build timestamps, commit SHAs, or artifact names:\n\n```yaml copy\nsteps:\n  - name: Store build timestamp\n    run: echo \"BUILD_TIME=$(date +'%T')\" >> $GITHUB_ENV\n\n  - name: Deploy using stored timestamp\n    run: echo \"Deploying at $BUILD_TIME\"\n```\n\n<div class=\"ghd-tool powershell\">\n\n> \\[!NOTE]\n> PowerShell versions 5.1 and below (`shell: powershell`) do not use UTF-8 by default, so you must specify the UTF-8 encoding. For example:\n>\n> ```yaml copy\n> jobs:\n>   legacy-powershell-example:\n>     runs-on: windows-latest\n>     steps:\n>       - shell: powershell\n>         run: |\n>           \"mypath\" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append\n> ```\n>\n> PowerShell Core versions 6 and higher (`shell: pwsh`) use UTF-8 by default. For example:\n>\n> ```yaml copy\n> jobs:\n>   powershell-core-example:\n>     runs-on: windows-latest\n>     steps:\n>       - shell: pwsh\n>         run: |\n>           \"mypath\" >> $env:GITHUB_PATH\n> ```\n\n</div>\n\n## Setting an environment variable\n\n> \\[!NOTE]\n> To avoid issues, it's good practice to treat environment variables as case sensitive, irrespective of the behavior of the operating system and shell you are using.\n\n<div class=\"ghd-tool bash\">\n\n```bash copy\necho \"{environment_variable_name}={value}\" >> \"$GITHUB_ENV\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n* Using PowerShell version 6 and higher:\n\n  ```powershell copy\n  \"{environment_variable_name}={value}\" >> $env:GITHUB_ENV\n  ```\n\n* Using PowerShell version 5.1 and below:\n\n  ```powershell copy\n  \"{environment_variable_name}={value}\" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append\n  ```\n\n</div>\n\nYou can make an environment variable available to any subsequent steps in a workflow job by defining or updating the environment variable and writing this to the `GITHUB_ENV` environment file. The step that creates or updates the environment variable does not have access to the new value, but all subsequent steps in a job will have access.\n\nYou can't overwrite the value of the default environment variables named `GITHUB_*` and `RUNNER_*`. Currently you can overwrite the value of the `CI` variable. However, it's not guaranteed that this will always be possible. For more information about the default environment variables, see [Store information in variables](/en/actions/learn-github-actions/environment-variables#default-environment-variables).\n\n> \\[!NOTE]\n> Due to security restrictions, `GITHUB_ENV` cannot be used to set the `NODE_OPTIONS` environment variable.\n\n### Example of writing an environment variable to `GITHUB_ENV`\n\n<div class=\"ghd-tool bash\">\n\n```yaml copy\nsteps:\n  - name: Set the value\n    id: step_one\n    run: |\n      echo \"action_state=yellow\" >> \"$GITHUB_ENV\"\n  - name: Use the value\n    id: step_two\n    run: |\n      printf '%s\\n' \"$action_state\" # This will output 'yellow'\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```yaml copy\nsteps:\n  - name: Set the value\n    id: step_one\n    run: |\n      \"action_state=yellow\" >> $env:GITHUB_ENV\n  - name: Use the value\n    id: step_two\n    run: |\n      Write-Output \"$env:action_state\" # This will output 'yellow'\n```\n\n</div>\n\n### Multiline strings\n\nFor multiline strings, you may use a delimiter with the following syntax.\n\n```text copy\n{name}<<{delimiter}\n{value}\n{delimiter}\n```\n\n> \\[!WARNING]\n> Make sure the delimiter you're using won't occur on a line of its own within the value. If the value is completely arbitrary then you shouldn't use this format. Write the value to a file instead.\n\n#### Example of a multiline string\n\nThis example uses `EOF` as the delimiter, and sets the `JSON_RESPONSE` environment variable to the value of the `curl` response.\n\n<div class=\"ghd-tool bash\">\n\n```yaml copy\nsteps:\n  - name: Set the value in bash\n    id: step_one\n    run: |\n      {\n        echo 'JSON_RESPONSE<<EOF'\n        curl https://example.com\n        echo EOF\n      } >> \"$GITHUB_ENV\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```yaml copy\nsteps:\n  - name: Set the value in pwsh\n    id: step_one\n    run: |\n      $EOF = (New-Guid).Guid\n      \"JSON_RESPONSE<<$EOF\" >> $env:GITHUB_ENV\n      (Invoke-WebRequest -Uri \"https://example.com\").Content >> $env:GITHUB_ENV\n      \"$EOF\" >> $env:GITHUB_ENV\n    shell: pwsh\n```\n\n</div>\n\n## Setting an output parameter\n\nSets a step's output parameter. Note that the step will need an `id` to be defined to later retrieve the output value. You can set multi-line output values with the same technique used in the [Multiline strings](/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings) section to define multi-line environment variables.\n\n<div class=\"ghd-tool bash\">\n\n```bash copy\necho \"{name}={value}\" >> \"$GITHUB_OUTPUT\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```powershell copy\n\"{name}=value\" >> $env:GITHUB_OUTPUT\n```\n\n</div>\n\n### Example of setting an output parameter\n\n<div class=\"ghd-tool bash\">\n\nThis example demonstrates how to set the `SELECTED_COLOR` output parameter and later retrieve it:\n\n```yaml copy\n      - name: Set color\n        id: color-selector\n        run: echo \"SELECTED_COLOR=green\" >> \"$GITHUB_OUTPUT\"\n      - name: Get color\n        env:\n          SELECTED_COLOR: ${{ steps.color-selector.outputs.SELECTED_COLOR }}\n        run: echo \"The selected color is $SELECTED_COLOR\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\nThis example demonstrates how to set the `SELECTED_COLOR` output parameter and later retrieve it:\n\n```yaml copy\n      - name: Set color\n        id: color-selector\n        run: |\n            \"SELECTED_COLOR=green\" >> $env:GITHUB_OUTPUT\n      - name: Get color\n        env:\n          SELECTED_COLOR: ${{ steps.color-selector.outputs.SELECTED_COLOR }}\n        run: Write-Output \"The selected color is $env:SELECTED_COLOR\"\n```\n\n</div>\n\n## Adding a job summary\n\n<div class=\"ghd-tool bash\">\n\n```bash copy\necho \"{markdown content}\" >> $GITHUB_STEP_SUMMARY\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```powershell copy\n\"{markdown content}\" >> $env:GITHUB_STEP_SUMMARY\n```\n\n</div>\n\nYou can set some custom Markdown for each job so that it will be displayed on the summary page of a workflow run. You can use job summaries to display and group unique content, such as test result summaries, so that someone viewing the result of a workflow run doesn't need to go into the logs to see important information related to the run, such as failures.\n\nJob summaries support [GitHub flavored Markdown](https://github.github.com/gfm/), and you can add your Markdown content for a step to the `GITHUB_STEP_SUMMARY` environment file. `GITHUB_STEP_SUMMARY` is unique for each step in a job. For more information about the per-step file that `GITHUB_STEP_SUMMARY` references, see [Environment files](#environment-files).\n\nWhen a job finishes, the summaries for all steps in a job are grouped together into a single job summary and are shown on the workflow run summary page. If multiple jobs generate summaries, the job summaries are ordered by job completion time.\n\n### Example of adding a job summary\n\n<div class=\"ghd-tool bash\">\n\n```bash copy\necho \"### Hello world! :rocket:\" >> $GITHUB_STEP_SUMMARY\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```powershell copy\n\"### Hello world! :rocket:\" >> $env:GITHUB_STEP_SUMMARY\n```\n\n</div>\n\n![Screenshot of the summary page of a workflow run. Under \"example summary\" is \"Hello world!\" and a rocket emoji.](/assets/images/help/actions/actions-job-summary-simple-example.png)\n\n### Multiline Markdown content\n\nFor multiline Markdown content, you can use `>>` to continuously append content for the current step. With every append operation, a newline character is automatically added.\n\n#### Example of multiline Markdown content\n\n<div class=\"ghd-tool bash\">\n\n```yaml\n- name: Generate list using Markdown\n  run: |\n    echo \"This is the lead in sentence for the list\" >> $GITHUB_STEP_SUMMARY\n    echo \"\" >> $GITHUB_STEP_SUMMARY # this is a blank line\n    echo \"- Lets add a bullet point\" >> $GITHUB_STEP_SUMMARY\n    echo \"- Lets add a second bullet point\" >> $GITHUB_STEP_SUMMARY\n    echo \"- How about a third one?\" >> $GITHUB_STEP_SUMMARY\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```yaml\n- name: Generate list using Markdown\n  run: |\n    \"This is the lead in sentence for the list\" >> $env:GITHUB_STEP_SUMMARY\n    \"\" >> $env:GITHUB_STEP_SUMMARY # this is a blank line\n    \"- Lets add a bullet point\" >> $env:GITHUB_STEP_SUMMARY\n    \"- Lets add a second bullet point\" >> $env:GITHUB_STEP_SUMMARY\n    \"- How about a third one?\" >> $env:GITHUB_STEP_SUMMARY\n```\n\n</div>\n\n### Overwriting job summaries\n\nTo clear all content for the current step, you can use `>` to overwrite any previously added content in Bash, or remove `-Append` in PowerShell\n\n#### Example of overwriting job summaries\n\n<div class=\"ghd-tool bash\">\n\n```yaml\n- name: Overwrite Markdown\n  run: |\n    echo \"Adding some Markdown content\" >> $GITHUB_STEP_SUMMARY\n    echo \"There was an error, we need to clear the previous Markdown with some new content.\" > $GITHUB_STEP_SUMMARY\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```yaml\n- name: Overwrite Markdown\n  run: |\n    \"Adding some Markdown content\" >> $env:GITHUB_STEP_SUMMARY\n    \"There was an error, we need to clear the previous Markdown with some new content.\" >> $env:GITHUB_STEP_SUMMARY\n```\n\n</div>\n\n### Removing job summaries\n\nTo completely remove a summary for the current step, the file that `GITHUB_STEP_SUMMARY` references can be deleted.\n\n#### Example of removing job summaries\n\n<div class=\"ghd-tool bash\">\n\n```yaml\n- name: Delete all summary content\n  run: |\n    echo \"Adding Markdown content that we want to remove before the step ends\" >> $GITHUB_STEP_SUMMARY\n    rm $GITHUB_STEP_SUMMARY\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\n```yaml\n- name: Delete all summary content\n  run: |\n    \"Adding Markdown content that we want to remove before the step ends\" >> $env:GITHUB_STEP_SUMMARY\n    Remove-Item $env:GITHUB_STEP_SUMMARY\n```\n\n</div>\n\nAfter a step has completed, job summaries are uploaded and subsequent steps cannot modify previously uploaded Markdown content. Summaries automatically mask any secrets that might have been added accidentally. If a job summary contains sensitive information that must be deleted, you can delete the entire workflow run to remove all its job summaries. For more information see [Deleting a workflow run](/en/actions/managing-workflow-runs/deleting-a-workflow-run).\n\n### Step isolation and limits\n\nJob summaries are isolated between steps and each step is restricted to a maximum size of 1MiB. Isolation is enforced between steps so that potentially malformed Markdown from a single step cannot break Markdown rendering for subsequent steps. If more than 1MiB of content is added for a step, then the upload for the step will fail and an error annotation will be created. Upload failures for job summaries do not affect the overall status of a step or a job. A maximum of 20 job summaries from steps are displayed per job.\n\n## Adding a system path\n\nPrepends a directory to the system `PATH` variable and automatically makes it available to all subsequent actions in the current job; the currently running action cannot access the updated path variable. To see the currently defined paths for your job, you can use `echo \"$PATH\"` in a step or an action.\n\n### Example of adding a system path\n\n<div class=\"ghd-tool bash\">\n\nThis example demonstrates how to add the user `$HOME/.local/bin` directory to `PATH`:\n\n```bash copy\necho \"$HOME/.local/bin\" >> \"$GITHUB_PATH\"\n```\n\n</div>\n\n<div class=\"ghd-tool powershell\">\n\nThis example demonstrates how to add the user `$env:HOMEPATH/.local/bin` directory to `PATH`:\n\n```powershell copy\n\"$env:HOMEPATH/.local/bin\" | Out-File -FilePath \"$env:GITHUB_PATH\" -Append\n```\n\n</div>"}