---
name: devsecops-devsecops-pipelinectl
title: pipelinectl
description: '`pipelinectl` is a lightweight key-value store that you can use in DevSecOps pipelines to share data between tasks and the compliance automation scripts.'
last-updated: 2026-07-27
---

> ## Documentation Index
> The table of contents for this documentation set is at https://cloud.ibm.com/docs/devsecops?format=markdown
> The index for all IBM Cloud docs is at: https://cloud.ibm.com/docs/llms.txt
> Use these files to discover more information as needed.

# pipelinectl
{: #devsecops-pipelinectl}

`pipelinectl` is a lightweight key-value store that you can use in DevSecOps pipelines to share data between tasks and the compliance automation scripts.
{: shortdesc}

For more information about where this tool is used, see [Adding test and build steps to pipelines](https://cloud.ibm.com/docs/devsecops?topic=devsecops-cd-devsecops-add-pipeline-steps&format=markdown).

## Cloud Object Storage configuration for pipeline data
{: #devsecops-pipelinectl-cos-config}

Cloud Object Storage (COS) provides unlimited, persistent storage for pipeline data such as build artifacts, test reports, and intermediate files. Unlike the default local storage, COS-backed files persist across pipeline runs and can be shared between different pipelines.

The data COS bucket must be separate from your evidence locker bucket due to audit and compliance requirements.
{: important}

### Configure COS for pipeline data
{: #devsecops-pipelinectl-cos-setup}

To use COS with pipelinectl file operations, complete the following configuration steps:

1. **Create a data bucket**

- You can use an existing Cloud Object Storage instance or create a new one. Follow the instructions in [Configuring Cloud Object Storage](https://cloud.ibm.com/docs/devsecops?topic=devsecops-cd-devsecops-cos-config&format=markdown) to:
- Create a data bucket (must be separate from your evidence locker bucket)
- Create a service credential for the bucket

2. **Configure IAM permissions**

Assign the following roles to your service credential for the data bucket: **Writer**, **Object Writer**, **Reader**, and **Content Reader**.

For detailed instructions, see [Bucket access permissions](https://cloud.ibm.com/docs/devsecops?topic=devsecops-cd-devsecops-cos-bucket-evidence&format=markdown#cd-devsecops-cos-bucket-permissions).

3. **Configure environment properties**

Add the following environment properties to your DevSecOps pipeline:

| Property | Type | Value | Description |
|----------|------|-------|-------------|
| `data-cos-api-key` | Secure | Your COS API key | API key from the service credential |
| `data-cos-bucket-name` | Text | Your bucket name | Name of your data bucket |
| `data-cos-endpoint` | Text | COS endpoint URL | Endpoint for your bucket's region |

To find your COS endpoint URL, go to your bucket's **Configuration** page and copy the endpoint for your bucket's region (for example, `s3.us-south.cloud-object-storage.appdomain.cloud`). Use the direct or private endpoint when possible for better performance and security.

Store the API key as a secure property to protect sensitive credentials.
{: important}

4. **Configure bucket lifecycle (recommended)**

Set a lifecycle policy to automatically delete old pipeline data. A 7-day expiration rule is recommended for most pipeline data. For instructions, see [Lifecycle policies](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-expiry&format=markdown).

### Understanding COS data scope
{: #devsecops-pipelinectl-cos-scope}

Unlike `save_result` and `set_env` commands, which are automatically scoped to individual pipeline runs, file operations using the COS backend (`--storage=cos`) operate on a shared bucket that persists across all pipeline runs.
{: important}

Key behaviors:

**No automatic run isolation** : Files saved with the same key from different pipeline runs overwrite each other.

**Shared bucket namespace** : All pipeline runs using the same COS configuration share the same bucket namespace.

**Persistent storage** : Files remain in COS until explicitly deleted or expired by bucket lifecycle rules.

**Scope comparison:**

| Command | Scope | Persistence |
|---------|-------|-------------|
| `save_result` | Single pipeline run | Run-specific |
| `set_env` | Single pipeline run | Run-specific |
| `save_file` (local) | Single pipeline run | Run-specific |
| `save_file --storage=cos` | **Shared across all runs** | **Persistent** |
{: caption="Table 1. Command scope comparison" caption-side="bottom"}

When you use `list_files --storage=cos`, the command returns ALL files in the configured bucket, not just files from the current pipeline run. Use prefix filtering to narrow results.
{: note}

### Best practices for COS file operations
{: #devsecops-pipelinectl-cos-best-practices}

Follow these best practices to organize and manage files effectively in Cloud Object Storage and avoid unintended data overwrites.

#### Avoiding conflicts

To prevent data overwrites and conflicts:

- Include unique identifiers in keys (for example, pipeline run ID, timestamp)
- Use hierarchical key patterns: `project/component/run-id/filename`
- Avoid generic keys like `build-artifact` without qualifiers

Example of conflict:

```bash
# Pipeline Run 1
save_file --storage=cos build-artifact ./dist/app-v1.0.0.tar.gz

# Pipeline Run 2 (overwrites Run 1's file!)
save_file --storage=cos build-artifact ./dist/app-v2.0.0.tar.gz
```
{: codeblock}

Example of safe usage:

```bash
# Pipeline Run 1
save_file --storage=cos "build-artifact-${PIPELINE_RUN_ID}" ./dist/app-v1.0.0.tar.gz

# Pipeline Run 2 (separate key, no conflict)
save_file --storage=cos "build-artifact-${PIPELINE_RUN_ID}" ./dist/app-v2.0.0.tar.gz
```
{: codeblock}

#### Key naming conventions

Use hierarchical patterns

Organize files with descriptive, hierarchical key names:

```bash
# Good: Organized, descriptive
save_file --storage=cos "artifacts/build/${PIPELINE_RUN_ID}/app.tar.gz" ./dist/app.tar.gz
save_file --storage=cos "reports/security/${BUILD_NUMBER}/scan.json" ./scan-results.json

# Avoid: Flat, generic
save_file --storage=cos "artifact" ./dist/app.tar.gz
```
{: codeblock}

Include unique identifiers

Use variables to make keys unique per pipeline run:

- Pipeline run ID: `${PIPELINE_RUN_ID}`
- Build number: `${BUILD_NUMBER}`
- Timestamp: `$(date +%Y%m%d-%H%M%S)`
- Git commit SHA: `${GIT_COMMIT}`

Use descriptive names

Choose clear, meaningful names that indicate the file's purpose:

```bash
# Good: Clear purpose
save_file --storage=cos "ui-service-image-${VERSION}" ./image.tar

# Avoid: Ambiguous
save_file --storage=cos "img" ./image.tar
```
{: codeblock}

#### Avoid reserved prefixes

Do NOT use keys starting with `devsecops-pipeline-data/` (for example, `devsecops-pipeline-data/path/to/file`). The `devsecops-pipeline-data/` prefix is reserved for internal pipeline operations. Using reserved prefixes may cause data corruption or pipeline failures.
{: important}

#### Filtering and retrieval

Use prefix-based filtering to narrow results when listing files:

```bash
# List all artifacts for a specific project
list_files --storage=cos "myproject/artifacts/"

# List security reports for a specific date
list_files --storage=cos "reports/security/2024-01-15"
```
{: codeblock}

Explicitly remove temporary files

When files are no longer needed, remove them explicitly:

```bash
remove_file --storage=cos "temp/build-${PIPELINE_RUN_ID}/cache.tar"
```
{: codeblock}

### Security considerations
{: #devsecops-pipelinectl-cos-security}

- **API Key Management**: Always store the `data-cos-api-key` as a secure property. Never hardcode API keys in scripts or configuration files.
- **Least Privilege**: Grant only the minimum required IAM permissions listed above.
- **Bucket Separation**: Use a dedicated bucket for pipeline data, separate from your evidence locker bucket.

## Usage
{: #pipelinectl-usage}

`pipelinectl` provides a single binary. Its behavior depends on its name (as in [busybox](https://www.busybox.net/about.html){: external}). When invoked as `pipelinectl`, the program must be provided as the first argument, for example `pipelinectl get_data`.

Available aliases and methods:

- [set_env](#set_env)
- [set_envc](#set_envc)
- [get_env](#get_env)
- [list_env](#list_env)
- [set_secret](#set_secret)
- [get_secret](#get_secret)
- [list_secrets](#list_secrets)
- [remove_secret](#remove_secret)
- [save_file](#save_file)
- [load_file](#load_file)
- [list_files](#list_files)
- [remove_file](#remove_file)
- [save_repo](#save_repo)
- [list_repos](#list_repos)
- [load_repo](#load_repo)
- [save_result](#save_result)
- [list_results](#list_results)
- [load_result](#load_result)
- [save_artifact](#save_artifact)
- [list_artifacts](#list_artifacts)
- [load_artifact](#load_artifact)
- [put_data](#put_data)
- [get_data](#get_data)
- [serialize](#serialize)
- [deserialize](#deserialize)
- [save_asset](#save_asset)
- [load_asset](#load_asset)
- [save_evidence](#save_evidence)
- [load_evidence](#load_evidence)
- [delete_evidences](#delete_evidences)

### set_env
{: #set_env}

```bash
# <key>: The name of the environment variable e.g. pipeline-namespace, app-name
# <value>: Value of the key
set_env <key> # reads <value> from `stdin`
set_env <key> <value>
```
{: codeblock}

Saves an arbitrary string that can be retrieved later on with [`get_env`](#get_env).

If the `<value>` argument is missing, `set_env` reads it from the standard input. `set_env` also supports passing multiple key value pairs to be set at once.

Example:

```bash
# set value provided as argument
set_env app-name "my-app-name"

# set value provided via stdin
echo "my-app-name" | set_env app-name
set_env my-api-key < /config/my-api-key

# set multiple key value pairs
set_env key-1 "value-1" \
  key-2 "value-2" \
  key-n "value-n"
```
{: codeblock}

### set_envc
{: #set_envc}

```bash
# <key>: The name of the environment variable e.g. pipeline-namespace, app-name
# <value>: Value of the key
set_envc <key> # reads <value> from `stdin`
set_envc <key> <value>
```
{: codeblock}

Saves an immutable arbitrary string that can be retrieved later on with [`get_env`](#get_env). Once saved with `set_envc`, it cannot be altered by further `set_env` / `set_envc` calls.

If the `<value>` argument is missing, `set_envc` reads it from the standard input. `set_envc` also supports passing multiple key value pairs to be set at once.

- Once set with `set_envc`, the key cannot be overwritten with further invocations of `set_envc` or `set_env`.
- Variables once already set with set_env, cannot be overwritten with `set_envc`. 

Example:

```bash
# set value provided as argument
set_envc app-name "my-app-name"

# set value provided via stdin
echo "my-app-name" | set_envc app-name
set_envc my-api-key < /config/my-api-key

# set multiple key value pairs
set_envc key-1 "value-1" \
  key-2 "value-2" \
  key-n "value-n"
```
{: codeblock}

### get_env
{: #get_env}

```bash
# <key>: The name of the environment variable e.g. pipeline-namespace, app-name
get_env <key> [default]
```
{: codeblock}

Print the stored configuration value (in this order):

* If `set_env` was used previously with `key`, it retrieves that value
* It tries to read the file `$CONFIG_DIR/$key` (`CONFIG_DIR` defaults to `/config`)
* It prints the specified default value (if there's any)
* It prints an error message, and returns a nonzero exit code

Example:

```bash
get_env app-name "default-app-name"
```
{: codeblock}

### list_env
{: #list_env}

```bash
list_env
```
{: codeblock}

Displays the saved keys and environment variables from the `set_env` process.

Example:

```bash
list_env
```
{: codeblock}

### set_secret
{: #set_secret}

```bash
# <key>: The name of the secret e.g. artifactory-token, (short-lived) iam-token
# <value>: Value of the secret
set_secret <key> # reads <value> from `stdin`
set_secret <key> <value>
```
{: codeblock}

Saves a secret that can be retrieved later on with [`get_secret`](#get_secret).

If the `<value>` argument is missing, `set_secret` reads it from the standard input.

- Unlike `set_env`, `set_secret` does **not** support passing multiple key value pairs to be set at once.
- The content set by `set_secret` does not get serialized, hence it will not be available across sub-pipelines / async pipelineruns .
- It is recommended to disable debug logging around this invocation, to ensure that the saved secret content does not show up even in debug logs.
- Ensure that scripts and any logic do not depend on any output of `set_secret` (there is a print statement done to mask the secret value utilising the [::add-mask:: functionality](https://cloud.ibm.com/docs/ContinuousDelivery?topic=ContinuousDelivery-cd_data_security&interface=ui&format=markdown#cd_add_mask_command))

Example:

```bash
# set value provided as argument
set_secret my-secret-key "my-secret-content"

# set value provided via stdin
echo "my-secret-content" | set_secret my-secret
set_secret my-api-key < /config/my-api-key

# set multiple key value pairs
set_secret secret-key-1 "value-1" \
  secret-key-2 "value-2" \
  secret-key-n "value-n"

```
{: codeblock}

### get_secret
{: #get_secret}

```bash
# <key>: The name of the secret set with set_secret or set as Secure Value in pipeline UI
get_secret <key> [default]
```
{: codeblock}

Retrieve the stored secret value (in this order):

* If `set_secret` was used previously with `key`, it retrieves that value
* It tries to read the file `$SECRET_CONFIG_DIR/$key` (`SECRET_CONFIG_DIR` defaults to `/config/secure-properties`)
* It prints the specified default value (if there's any)
* It prints an error message, and returns a nonzero exit code

Example:

```bash
get_secret cookie-token "default-token"
```
{: codeblock}

```bash
get_secret specific-account-ibmcloud-api-key "$(get_secret ibmcloud-api-key "")"
```
{: codeblock}

#### Always quote variables that hold secret values
{: #get_secret-quoting}

When you store a secret value in a shell variable and then use that variable, always wrap it in double quotes. Without quotes, the shell can break the value across multiple words before passing it to a command.

Do not use unquoted variables with secret values.
{: important}

```bash
export API_KEY=$(get_secret my-api-key)

# Unsafe: a multi-line secret value is not passed intact.
# Parts of the secret may appear unmasked in the pipeline log.
some-cli login --apikey $API_KEY
```
{: codeblock}

Always quote the variable to keep the value intact.

```bash
export API_KEY=$(get_secret my-api-key)

# Safe: the value is passed as a single, intact string.
some-cli login --apikey "$API_KEY"
```
{: codeblock}

The same rule applies wherever the variable is used - in command arguments, string interpolation, or when writing values to a file.

```bash
# Safe
curl -H "Authorization: Bearer $API_KEY" https://example.com/api
echo "$API_KEY" > /tmp/credentials.txt
```
{: codeblock}

### list_secrets
{: #list_secrets}

```bash
list_secrets
```
{: codeblock}

Displays the saved keys from the `set_secret` process and Secure Value type environment variables in the pipeline UI.

Example:

```bash
list_secrets
```
{: codeblock}

### remove_secret
{: #remove_secret}

```bash
remove_secret <key>
```

This command unsets the secret stored inside the pipelinectl, which were saved using `set_secret`.

### save_file
{: #save_file}

```bash
# <identifier>: Name used to store and retrieve the file (for example, 'build-artifact', 'my-report')
# <path>: Path to the file on the local filesystem (for example, './dist/app.tar.gz')
save_file <identifier> <path>
```
{: codeblock}

Saves an arbitrary file that can be retrieved later on with [`load_file`](#load_file).

Directories are not supported.
{: note}

**Local Storage (Default):**

Files are stored in the pipeline workspace and are scoped to the current pipeline run.

```bash
save_file some_config ./config.yaml
```
{: codeblock}

**COS Storage:**

Files are stored in Cloud Object Storage and persist across pipeline runs. See [Data Scope and Persistence](#devsecops-pipelinectl-file-scope) for important information about shared bucket behavior.

Prerequisites: Ensure COS is configured. See [Cloud Object Storage configuration](#devsecops-pipelinectl-cos-config).
{: note}

```bash
# Save with run-specific key
save_file --storage=cos "build-artifact-${PIPELINE_RUN_ID}" ./dist/app-v1.2.3.tar.gz

# Save with hierarchical key
save_file --storage=cos "artifacts/ui-service/${BUILD_NUMBER}/image.tar" ./image.tar

# Save report with timestamp
save_file --storage=cos "reports/security/$(date +%Y%m%d)/scan.json" ./scan-results.json
```
{: codeblock}

### load_file
{: #load_file}

```bash
# <identifier>: Name of the file to retrieve (for example, 'build-artifact', 'my-report')
load_file <identifier>
```
{: codeblock}

Prints the saved file to `stdout`.

**Local Storage (Default):**

Retrieves files stored in the pipeline workspace for the current run.

```bash
load_file some_config > some_config.yaml
```
{: codeblock}

**COS Storage:**

Retrieves files from Cloud Object Storage.

Prerequisites: Ensure COS is configured. See [Cloud Object Storage configuration](#devsecops-pipelinectl-cos-config).
{: note}

```bash
# Load file and print to stdout
load_file --storage=cos "build-artifact-${PIPELINE_RUN_ID}"

# Load file and save to local filesystem
load_file --storage=cos "artifacts/ui-service/${BUILD_NUMBER}/image.tar" > ./downloaded-image.tar
```
{: codeblock}

### list_files
{: #list_files}

Lists all stored files saved via `save_file`, optionally filtered by a key prefix.

```bash
# <prefix>: (optional) Filter results to keys starting with this prefix
list_files <prefix>
```
{: codeblock}

Prints the list of file keys to `stdout`.

**Local Storage (Default):**

Lists files stored in the pipeline workspace for the current run.

```bash
list_files # lists all saved files

list_files saved-reports- # lists files with "saved-reports-" prefix
```
{: codeblock}

**COS Storage:**

Lists files from Cloud Object Storage. Returns ALL files in the configured bucket, not just files from the current pipeline run. Use the optional prefix parameter to filter results and narrow down to specific files.
{: important}

Prerequisites: Ensure COS is configured. See [Cloud Object Storage configuration](#devsecops-pipelinectl-cos-config).
{: note}

```bash
# List all files in bucket (may include files from multiple runs)
list_files --storage=cos

# List files with specific prefix to narrow results
list_files --storage=cos "artifacts/ui-service/"

# List files for specific date
list_files --storage=cos "reports/security/20240115"
```
{: codeblock}

### remove_file
{: #remove_file}

Removes a stored file.

```bash
# <identifier>: Name of the file to remove (for example, 'build-artifact', 'my-report')
remove_file <identifier>
```
{: codeblock}

**Local Storage (Default):**

Removes files from the pipeline workspace for the current run.

```bash
remove_file my-report
```
{: codeblock}

**COS Storage:**

Removes files from Cloud Object Storage.

Prerequisites: Ensure COS is configured. See [Cloud Object Storage configuration](#devsecops-pipelinectl-cos-config).
{: note}

```bash
# Remove specific file
remove_file --storage=cos "build-artifact-${PIPELINE_RUN_ID}"

# Remove temporary file
remove_file --storage=cos "temp/cache-${BUILD_NUMBER}.tar"
```
{: codeblock}

### save_repo
{: #save_repo}

```bash
# <key>:  Key of the repository e.g. repository name
# <prop>: Type of the property, e.g. url, branch, commit etc.
# <value>: Value of the property
save_repo <key> [<prop>=<value> ...]
```
{: codeblock}

Registers a new repository with the pipeline or updates an existing one.

Supported properties:

- `url`: The URL that can be used to clone the repository.
- `path`: Location of the cloned repository relative to the workspace root.

Other property names can be used as well, but to avoid naming collisions, they must be prefixed with a service-specific identifier, for example instead of using `foo`, use `my-service.foo`.

Example:

```bash
save_repo app_ui "url=${REPO_URL}" "path=app_ui_repo"
save_repo app_ui "branch=${REPO_BRANCH}"
save_repo app_ui "commit=${REPO_SHA}"

# any additional property can be added
save_repo app_ui "commit=${REPO_SHA}"
```
{: codeblock}

#### Using stdin as a value source
{: #stdin-value-source}

Values can be provided from stdin, if the following conditions are true:

- The content is streamed for the command
- One property does not have a value and `=`

Example:

```bash
command_with_large_output | save_repo app_ui "issues"

# this also works with multiple properties,
# but stdin can provide value for only a single one
command_with_large_output | save_repo app_ui "issues" "result=success" "commit=${REPO_SHA}"
```
{: codeblock}

If multiple values are missing with `=` the command exits with an error, because it cannot determine
which property belongs to the value on `stdin`.

Properties without a value but still appending `=` have an empty string as a value.

```bash
save_repo app_ui "bar="
load_repo app_ui bar # returns an empty string
```
{: codeblock}

### list_repos
{: #list_repos}

```bash
list_repos
```
{: codeblock}

Lists the `<key>` of the stored repos to `stdout`.

Example:

```bash
list_repos
# returns the list of stored repository keys to stdout for example:
#  app_ui
#  app_repo
```
{: codeblock}

### load_repo
{: #load_repo}

```bash
# <key>: Key of the repository, e.g. repository name
# <prop>: Name of the property, e.g. commit, branch, url
load_repo <key> [<prop>]
```
{: codeblock}

Prints the value of the specified property of the repository.
Lists all available properties for the repository when only the repository is provided.
Returns an error indicating no matching properties were found if the provided repository or property is invalid.

Description:

- Prints the value of the specified property of the repository, if  <key> and <prop> values are provided.
- Lists all available properties for the repository when only the <key> is provided.
- Returns an error indicating no matching properties were found if the provided <key> is invalid.

Example 1: Fetching a specific property:

```bash
REPO_SHA=$(load_repo app_ui commit)
```
{: codeblock}

Example 2: Listing all properties for a given repository:

```bash
REPO_SHA=$(load_repo app_ui)
```
{: codeblock}


Used with `list_repos` for retrieving property values

```bash
#
# iterate over all repos and print their URLs
#
while read -r key; do
  url=$(load_repo $key url)
  echo "Repository saved as '$key' is at: '$url'"
done < <(list_repos)
```
{: codeblock}

Outputs the following lines to the console:

When retrieving a specific property:

```text
 Repository saved as 'my-frontend' is at: 'github.com/my-team/frontend'
 Repository saved as 'my-backend' is at: 'github.com/my-team/backend'
```
{: screen}

When listing all properties for a given repository:

```text
 Properties available for '$key'.
```
{: screen}

### save_result
{: #save_result}

```bash
# <stage>: Stage name e.g. test, detect-secrets, static-scan
# <path>: Path where will be stored the file, string
save_result  <stage> <path>
```
{: codeblock}

Saves an arbitrary test, scan result file for a stage. Later this file can be retrieved with `load_result`. By default, data is saved with the workspace-relative path as key.

Using the `PIPELINECTL_USE_PATH_AS_KEY` feature flag, data is saved with the provided path as the key.

Example:

```bash
#
# save the contents of the file ./results/mocha_results.json
# as an entry named "mocha_results.json" for the "test" stage
#
save_result test ./results/mocha_results.json

#
# save the contents of the file ../data/coverage.xml
# as an entry named "coverage.xml" for the "test" stage
#
save_result test ../data/coverage.xml

#
# Using the `PIPELINECTL_USE_PATH_AS_KEY` environment variable
# save the contents of the file ../data/coverage.xml
# as an entry named "../data/coverage.xml" for the "test" stage
#
PIPELINECTL_USE_PATH_AS_KEY=1 save_result test ../data/coverage.xml
```
{: codeblock}

### list_results
{: #list_results}

```bash
# <stage>: Stage name
list_results <stage>
```
{: codeblock}

Lists the saved file names for a stage.

Example:

```sh
list_results test
# mocha_results.json
# coverage.xml
```
{: codeblock}

### load_result
{: #load_result}

```bash
# <stage>: Stage name e.g. test, detect-secrets, static-scan
# <file>: File name e.g. mocha_results.json
load_result <stage> <file>
```
{: codeblock}

Prints the saved file keys to `stdout`. By default, a key is the workspace-relative path of the provided file path in `save_result`. Using the `PIPELINECTL_USE_PATH_AS_KEY` feature flag, a key is the path of the provided file path in `save_result`. To get the exact list of keys, use `list_results`.

Example:

```bash
load_result test mocha_results.json

#
# Using the `PIPELINECTL_USE_PATH_AS_KEY` environment variable
PIPELINECTL_USE_PATH_AS_KEY=1 load_result test ../data/coverage.xml
```
{: codeblock}

Used together with `list_results`

```bash
#
# iterate over all results stored for "test"
# and write them to the filename they were registered with
#
while read -r filename; do
  load_result test "$filename" > "./$filename"
done < <(list_results test)
```
{: codeblock}

### save_artifact
{: #save_artifact}

```bash
# <key>: Key of the artifact e.g. app-image, baseimage etc.
# <prop>: Type of property e.g. name, type, tags, signature
# <value>: Value of the property
save_artifact <key> [<prop>=<value> ...]
```
{: codeblock}

Registers a new build artifact with the pipeline or updates an existing one.

#### Container images
{: #pipelinectl-container-images}

Some suggested properties that you can use:

- `type`: Can be any artifact type including `image`.
- `name`: A fully qualified name for the artifact. For example, for an image, something that can be used by `docker pull`.
- `signature`: A valid signature.
- `digest`: A `sha256` digest.
- `source`: For example, `http://<some-git-url>/blob/<commithash>/<path-to-file>`

Any properties can be set on top of these properties.

For an image, the `name` property must also contain the tag for the image.
{: tip}

Example:

```bash
save_artifact ui_service "name=us.icr.io/team_namespace/ui_service:2.4.3"
save_artifact ui_service "type=image"

# any additional property can be added
save_artifact ui_service "tags=latest,2.4.3,feat-something"

# later, when the image was signed, and we have signature data
save_artifact ui_service "signature=${SIGNATURE}"
```
{: codeblock}


#### Using stdin as a value source
{: #stdin-value-source-save-artifact}

Values can be provided from stdin, if the following are true:

- The content is streamed for the command
- One property does not have a value and `=`

Example:

```bash
command_with_large_output | save_artifact ui_service "issues"

# this also works with multiple properties,
# but stdin can provide value for only a single one
command_with_large_output | save_artifact ui_service "issues" "result=success" "signature=${SIGNATURE}"
```
{: codeblock}

If multiple values are missing with `=` the command exits with an error, because it cannot determine which property belongs to the value on stdin.

Properties without a value but still appending `=` have an empty string as a value.

```bash
save_artifact ui_service "bar="
load_artifact ui_service bar # returns an empty string
```
{: codeblock}

### list_artifacts
{: #list_artifacts}

```bash
list_artifacts
```
{: codeblock}

Lists the `<key>` of the stored artifacts to `stdout`.

Example:

```bash
list_artifacts
# returns the list of stored artifact keys to stdout for example:
#
# ui_service
# app_service
```
{: codeblock}

### load_artifact
{: #load_artifact}

```bash
# <key>: Name of the artifact e.g. app-image, baseimage etc.
# <prop>: Type of property e.g. name, type, tags, signature
load_artifact <key> [<prop>]
```
{: codeblock}

Description:

- Prints the value of the specified property of the repository, if  <key> and <prop> values are provided.
- Lists all available properties for the repository when only the <key> is provided.

Example 1: Fetching a specific property:

```bash
SIGNATURE=$(load_artifact ui_service signature)
```
{: codeblock}

Example2: Listing all properties for a given artifact:

```bash
load_artifact ui_service
```
{: codeblock}

Used with `list_repos` for retrieving property values

```bash
#
# iterate over all artifacts and print their image names
#
while read -r key; do
  image=$(load_artifact $key name)
  echo "Artifact saved as '$key' is named: '$image'"
done < <(list_artifacts)
```
{: codeblock}

Outputs the following lines to the console:

When retrieving a specific property:

```text
 Artifact saved as 'ui_service' is named: 'us.icr.io/team_namespace/ui_service:2.4.3'
 Artifact saved as 'backend_service' is named: 'us.icr.io/team_namespace/backend_service:2.4.3'
```
{: screen}

When listing all properties for a given artifact:

```text
 Properties available for 'ui_service': name, type, tags, signature
```
{: screen}

### Serialize
{: #serialize}

Serialize `pipelinectl` data into a transferable JSON file to be used as payload for pipeline webhook triggers. It can serialize repositories set by `save_repo`, artifacts set by `save_artifact`, and environment variables set by `set_env`.

(Optional) flags:

```bash
--all-repos         # all the repository information set by `pipelinectl`
--all-artifacts     # all the artifacts information set by `pipelinectl`
```
{: codeblock}

Example:

The following code saves all the repositories, all the artifacts and `<env_variable1>`, `<env_variable2>` into the `foo.json` file:

```bash
pipelinectl serialize --all-repos --all-artifacts <env_variable1> <env_variable2> > foo.json
```
{: codeblock}
This command is not an alias. You need `pipelinectl` explicitly.
{: note}


### deserialize
{: #deserialize}

Deserialize the `pipelinectl` from JSON to files, so `pipelinectl` can work in the triggered pipeline. Use the JSON that is serialized by the `pipelinectl serialize` command as the argument.

Example:

```bash
pipelinectl deserialize ./foo.json
```
{: codeblock}
This command is not an alias, need `pipelinectl` explicitly.
{: note}


## Low-level methods
{: #low-level-methods}

These methods are only exposed for the sake of completeness. Use the methods only on rare occasions.

### put_data
{: #put_data}

```bash
# <key>: Name of the data
# <prop>: Type of property e.g. name, type, tags, signature
# <value>: Value of the property
put_data <key> <prop> <value>
```
{: codeblock}

Sets `prop` to `value` for the entry defined by `key`.

### get_data
{: #get_data}

```bash
# <key>: Key of data
# <prop>: Type of property e.g. name, type, tags, signature
# <value>: Value of the property
get_data <key>
get_data <key> <prop>
```
{: codeblock}

Prints `prop` of the entry that is defined by `key`. If `prop` is not provided, it returns all of the `prop`s for the `key`. Returns a nonzero exit code when `key` has no `prop`.

### save_asset
{: #save_asset}

```bash
# <prop>: Type of property; for example, uri, id, blob
# <value>: Value of the property
save_asset <prop1> <value1> blob <json_string or path to a json file>
save_asset <prop1> <value1> <prop2> <value2> blob <json_string  or path to a json file>
```

Saves asset information to the pipelinectl storage to be accessible throughout the pipeline. Arbitrary numbers of properties are allowed. However, `blob` is a reserved property that is mandatory to be passed, and its corresponding value should be a filepath to a valid json file or a valid json string. The `save_asset` property creates immutable entries. It cannot be called twice for the same combination of `<prop> <value>` pairs.

### load_asset
{: #load_asset}

```bash
# <prop>: Type of property; for example, uri, id
# <value>: Value of the property
load_asset # retrieves all assets stored by save_asset
load_asset <prop1> <value1> # retrieves one asset that matches prop1 = value1 saved during save_asset
load_asset <prop1> <value1> <prop2> <value2> # retrieves one asset that matches prop1 = value1 AND prop2 = value2 saved during save_asset
```

Retrieves an asset that matches the provided `<prop> <value>` pairs. If called without a `<prop> <value>` combination, it retrieves all the assets that are saved using `save_asset` in the pipeline inside a json array. The `blob` property is a reserved property, so it cannot be used as a matching property for `load_asset`.

### save_evidence
{: #save_evidence}

```bash
# <prop>: Type of property; for example, blob, sha
# <value>: Value of the property
save_evidence <prop1> <value1> blob <json_string  or path to a json file>
save_evidence <prop1> <value1> <prop2> <value2> blob <json_string  or path to a json file>
```

Saves evidence information to the pipelinectl storage to be accessible throughout the pipeline. Arbitrary numbers of properties are allowed. However, the `blob` property is a reserved property that is mandatory to be passed, and its corresponding value should be a filepath to a valid json file or a valid json string. The `save_evidence` property creates immutable entries. It cannot be called twice for the same combination of `<prop> <value>` pairs.

### load_evidence
{: #load_evidence}

```bash
# <prop>: Type of property; for example, id, sha
# <value>: Value of the property
load_evidence # retrieves all evidences that are stored by save_evidence
load_evidence <prop1> <value1> # retrieves one evidence that matches prop1 = value1 saved during save_evidence
load_evidence <prop1> <value1> <prop2> <value2> # retrieves one evidence that matches prop1 = value1 AND prop2 = value2 saved during save_evidence
```

Retrieves an evidence that matches the provided `<prop> <value>` pairs. If called without a `<prop> <value>` combination, it retrieves all the evidences that are saved using `save_evidence` in the pipeline inside a json array. The `blob` property is a reserved property, so it cannot be used as a matching property for `load_evidence`.

### delete_evidences
{: #delete_evidences}

```bash
delete_evidences # deletes all the evidences stored inside pipelinectl so far using save_evidence
```

This command clears out all the evidences stored inside the pipelinectl, which were saved using `save_evidence`.

### save_string (deprecated)
{: #save_string}

`save_string` is deprecated, use `set_env` instead.
{: deprecated}

```bash
save_string <key> <value>
```
{: codeblock}

Saves an arbitrary string that can be retrieved later on with `load_string`.

### load_string (deprecated)
{: #load_string}

`load_string` is deprecated, use `get_env` instead.
{: deprecated}

```bash
load_string <key>
```
{: codeblock}

Prints the string that is stored in `key`.