# atmos artifacts publish

Publish a local file or directory to one configured repository as a named, versioned artifact. Republishing identical content changes nothing, and replacing different content at the same reference is an explicit, forced act.

> ⚠️ Experimental

## Usage

```shell
atmos artifacts publish <source> --repository=<alias> --name=<name> --version=<version> [flags]
```

## Examples

```shell
# Publish a directory
atmos artifacts publish ./dist --repository=backups --name=builds/app --version=build-123

# Replace an existing reference with different content
atmos artifacts publish ./dist --repository=backups --name=builds/app --version=build-123 --force

# Plan a publication without writing anything
atmos artifacts publish ./dist --repository=backups --name=builds/app --version=build-124 --dry-run

# Attach labels and documents
atmos artifacts publish ./dist --repository=backups --name=builds/app --version=build-125 \
  --labels=team=platform,purpose=backup --readme=README.md --changelog=CHANGELOG.md

# Machine-readable result
atmos artifacts publish ./dist --repository=backups --name=builds/app --version=build-126 --format=json
```

## Behavior

The name comes from `--name`, then from metadata the producer supplies, then from the source basename. The version comes from `--version`, then from producer metadata; when neither exists the command fails, because Atmos never generates a version. The kind defaults to `files`.

Atmos compares content, documents, and user metadata before it writes. An identical publication is a no-op that returns the existing Record with `outcome: unchanged`. Different content at the same reference fails until you pass `--force`, which creates a replacement Record (`outcome: replaced`) and updates the reference. Bytes addressed by an old digest are not modified.

`--force` does not bypass authentication, signature verification, or the immutability of plugin releases.

The reserved `.atmos/artifact/` directory of the source holds the distribution `README.md` and `CHANGELOG.md`. Use `--readme` and `--changelog` to point at other files, given relative to the source directory. A root `README.md` remains ordinary payload.

A dry run prepares the artifact and prints the files it selected, the metadata, and the documents. It writes to no repository and does not resolve credentials.

Writes are serialized by a lock. Local and OCI repositories lock at host scope by default. A repository configured with `locking.repository` takes its lock from that coordinator (for example an `aws/s3` repository) and the result reports the actual `lock_scope`.

## Arguments

- **`source` (required)** — A local file or directory. Symlinks that stay inside the source are preserved; absolute or escaping links, devices, and sockets are rejected.

## Flags

- **`--repository`, `-r` (required)** — Configured repository alias.
  Environment variable: `ATMOS_ARTIFACTS_REPOSITORY`
- **`--name` (optional)** — Artifact name. Defaults to producer metadata, then the source basename.
  Environment variable: `ATMOS_ARTIFACTS_NAME`
- **`--version` (required unless the producer supplies one)** — Artifact version label.
  Environment variable: `ATMOS_ARTIFACTS_VERSION`
- **`--kind` (optional)** — Artifact kind. Defaults to `files`.
  Environment variable: `ATMOS_ARTIFACTS_KIND`
- **`--labels` (optional)** — Exact `key=value` labels, comma-separated and/or repeated. `key:value` is also accepted. Label keys cannot contain `=`, `:`, or `,`, and values cannot contain `,`.
  Environment variable: `ATMOS_ARTIFACTS_LABELS`
- **`--readme` (optional)** — README path, relative to the source directory.
  Environment variable: `ATMOS_ARTIFACTS_README`
- **`--changelog` (optional)** — CHANGELOG path, relative to the source directory.
  Environment variable: `ATMOS_ARTIFACTS_CHANGELOG`
- **`--force`, `-f` (optional)** — Replace an existing artifact that has different content.
  Environment variable: `ATMOS_ARTIFACTS_FORCE`
- **`--dry-run`, `-n` (optional)** — Validate and plan the publication without writing anything.
  Environment variable: `ATMOS_ARTIFACTS_DRY_RUN`
- **`--format` (optional)** — Output format: `text` (default), `json`, or `yaml`.
  Environment variable: `ATMOS_ARTIFACTS_FORMAT`

## Output

Stdout carries the result: `outcome`, `ref`, `location`, `resolved_digest`, `record_digest`, `content_digest`, `representation_digest`, `size`, and `lock_scope`. A dry run adds the kind, labels, file count, documents, and the list of selected files; the structured result adds the sealed `record`. Stderr carries the status line, for example `Published builds/app:build-123 to repository backups (created).`

## Errors

- **Missing repository** — Exit code 2. The hint lists the configured aliases. No default repository is chosen.
- **Unknown repository alias** — Fails with an invalid artifact configuration error that lists the configured aliases.
- **Missing version** — Fails before anything is staged or written, unless the producer supplies a version.
- **Conflict** — Different content at an existing reference fails with an artifact conflict. Re-run with `--force`. A plugin release stays immutable even with `--force`.
- **Invalid name, version, kind, or label** — Rejected before any write. Atmos never rewrites case or characters to make them fit.
- **Unsupported capability or lock failure** — A repository that cannot provide the required lock scope, or whose lock is held by another writer, fails before the artifact is written. Atmos never steals another writer's lock.

Every failure exits with a nonzero status. For failures reached while the command runs, `--format=json` or `--format=yaml` still writes the result to stdout with `outcome: failed` and an `error` field. Argument and flag parsing failures, such as a missing reference or an unknown flag, are rejected before the command runs and do not produce a structured result.

## Related

- [`atmos artifacts pull`](/cli/commands/artifacts/pull)
- [`atmos artifacts inspect`](/cli/commands/artifacts/inspect)
- [`atmos artifacts sign`](/cli/commands/artifacts/sign)
- [Artifacts Configuration](/cli/configuration/artifacts)
