ORAS CLI: the OCI registry client for files that are not container images
OCI registry client - managing content like artifacts, images, packages
At a glance
- What is it?
- ORAS CLI pushes and pulls arbitrary artifacts to any OCI-compliant registry using the same content-addressed storage that holds container images. This review covers what it does, how it is built, and where the tool stops being the right answer.
- Who is it for?
- Adopt ORAS CLI when your artifacts already live next to container images and you want one registry, one credential store and one retention policy for both. Skip it when your consumers expect a package manager or a plain HTTP file server, because a registry is not either of those.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What ORAS CLI solves, and for whom
A container registry is a content-addressed blob store with a naming and authentication layer on top. Nothing in that design is specific to container images. ORAS CLI exposes the registry as a general artifact store, so a Helm chart, a WASM module, a signed SBOM, a machine learning model or a binary release tarball can be pushed and pulled with the same verbs used for images.
The people who get the most out of it are platform and release engineers who already run a registry. If your organization has a registry with retention rules, replication, access control and audit logging, ORAS CLI turns that investment into storage for everything else. You do not stand up a second artifact server, and you do not hand out a second set of credentials.
It is less obviously useful if you have no registry. ORAS CLI is a client; it does not ship a server. Point it at a registry you already operate, whether that is a hosted service or something self-hosted. The project's own release images are published to GitHub Container Registry, which is one place the client is routinely pointed at.
The command surface is deliberately small. The repository layout puts the entry point under cmd/oras and the implementation under internal/, with the heavy lifting delegated to the oras.land/oras-go/v2 module listed in go.mod. That split matters for adopters: the CLI is a thin front end over a library you can also call directly from Go.
How the OCI distribution model shapes what you can store
ORAS CLI speaks the OCI distribution specification. Content is addressed by digest, so a blob's identity is the hash of its bytes, and a tag is a movable pointer to a digest. Pushing an artifact means uploading blobs, then uploading a manifest that references them, then optionally attaching a tag.
That model has consequences worth understanding before you migrate anything. Two pushes of identical bytes cost one blob of storage. A tag can be reassigned without deleting the old content, which is why registries need garbage collection to reclaim space. Deleting a tag does not necessarily delete the underlying blobs.
The manifest is where artifact semantics live. The OCI image specification defines media types for config and layers, and ORAS uses those fields for non-image payloads: one blob carries a small config document describing the artifact, and the remaining blobs are its content. Tools that assume every manifest describes a runnable image will misread an ORAS artifact, and some older registries reject manifests whose config media type they do not recognize.
The project's release process reflects the same tagging discipline. Release images are published for multiple architectures, with `:main` tracking the latest merge on the default branch, `:vX.Y.Z` as the immutable version tag, `:vX.Y` tracking the latest stable patch in a minor line, `:vX` tracking the latest stable release in a major line, and `:latest` tracking the highest stable release across all major versions. The README states that prereleases never move rolling tags, and that a maintenance-branch release only moves the rolling tags for its own minor and major lines when it is newer than the current tag in that line. That rule exists to stop `:latest` from moving backwards after a backport, and it is a good illustration of how much behaviour a registry client inherits from tag convention rather than from the protocol itself.
Where the project says to get ORAS CLI, and how it is built
The README does not contain install instructions. It points to the project website at oras.land, where the CLI documentation lives under oras.land/cli, and it notes that release images are published for multiple architectures to GitHub Container Registry under `ghcr.io/oras-project/oras`. So the two paths the project itself names are the website documentation and the published release image. Anything else is a third-party packaging choice that the repository does not describe.
What the repository does describe is the build. The Dockerfile uses a two-stage build. The first stage is based on `docker.io/library/golang:1.27.1-alpine`, installs `git` and `make`, copies the source into `/oras`, and runs the platform-specific build target:
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.27.1-alpine as builder
ARG TARGETPLATFORM
RUN apk add git make
ENV ORASPKG /oras
ADD . ${ORASPKG}
WORKDIR ${ORASPKG}
RUN make "build-$(echo $TARGETPLATFORM | tr / -)"
RUN mv ${ORASPKG}/bin/${TARGETPLATFORM}/oras /go/bin/orasThe second stage starts from `docker.io/library/alpine:3.24.2`, adds `ca-certificates`, copies the binary to `/bin/oras`, creates `/workspace` as the working directory, and sets the entrypoint to `/bin/oras`. Because the entrypoint is the binary itself, arguments pass straight through to the CLI.
The Makefile exposes the same build target directly. Its default target is `lint test build-$(OS)-$(ARCH)`, and the OS and architecture are derived from `uname -o` and `uname -m`, mapping Darwin to `mac` and anything else to `linux`, and arm64 to `arm64` and anything else to `amd64`. The release target list covers darwin_amd64, darwin_arm64, linux_amd64, linux_arm64, linux_armv7, linux_s390x, linux_ppc64le, linux_riscv64, linux_loong64, windows_amd64, windows_arm64 and freebsd_amd64, which tells you the set of platforms the project builds for even though the README is silent on how to install any of them.
Building from source requires the Go toolchain version declared in go.mod, which is Go 1.26.7, and the module pins oras.land/oras-go/v2 v2.6.2 along with cobra, pflag, logrus and the OCI image-spec and go-digest packages. There is also a snapcraft.yaml at the repository root, but the README does not document a snap channel, so treat that as an artifact of the build system rather than a supported install route.
Where ORAS CLI is the wrong tool
A registry is not a package manager. ORAS CLI has no dependency resolution, no version constraint solving and no lockfile. If your consumers expect `npm install` or `pip install` semantics, pushing tarballs to a registry does not give them that; it gives them a URL and a digest they must wire up themselves.
Garbage collection is the second sharp edge. Because tags are pointers and blobs are shared, an artifact that is pushed but never tagged is reachable only by digest. Whether your registry preserves it depends on the registry's own GC policy, which ORAS CLI does not control and the README does not document. If your workflow depends on untagged artifacts surviving, that is a property of your registry configuration, and it needs to be verified there.
The third constraint is registry compatibility. ORAS relies on the registry accepting OCI artifact manifests. Registries that predate the artifact guidance, or that enforce image-specific validation, may reject a push that a modern registry accepts. The client cannot paper over that.
Finally, size and network shape matter. Large artifacts pushed through a registry inherit the registry's upload and download behaviour. ORAS CLI is a client, and its throughput is bounded by the registry endpoint and the network path to it. For a multi-gigabyte model file distributed to many consumers, a CDN-backed object store may simply be cheaper and faster, even though the registry would work.
ORAS CLI compared with the Docker CLI and skopeo
The closest alternative most engineers already have installed is the Docker CLI. Docker can push and pull images, and with buildx it can attach attestations and SBOMs to an image. The difference is framing. Docker's mental model is an image built from a Dockerfile; attaching a non-image file means attaching it to something that is already an image. ORAS starts from the artifact itself. You push a file and a manifest is created for it, with no image required at any point.
Skopeo is a better comparison because it is also registry-native and image-aware. Skopeo copies images between registries and inspects remote images without a daemon. Its centre of gravity is image transport and inspection. ORAS CLI's centre of gravity is arbitrary content, which is why the artifact-oriented verbs are the primary interface rather than a side feature.
The practical difference shows up in what you have to explain to a new teammate. With ORAS, the explanation is "we store build outputs in the registry". With Docker, the explanation usually starts with a base image that exists only to satisfy the tool.
One more distinction matters for Go shops. ORAS CLI is a front end over the oras.land/oras-go/v2 library, so the same operations are available programmatically. A team that outgrows shelling out to the binary can move to the library without changing the storage model underneath.
Maintenance status, releases and licence
The repository is not archived, and the last push was on 2026-09-28. Recent releases are v1.3.2 on 2026-04-18, v1.3.3 on 2026-07-10 and v1.3.4 on 2026-08-27. That is a steady patch cadence rather than a stream of breaking changes, which is what you want from a client whose correctness depends on a specification other people implement.
Upgrade cost is mostly a function of the Go module dependency. The CLI pins oras.land/oras-go/v2 v2.6.2 and requires Go 1.26.7 in go.mod, while the Dockerfile builds with golang:1.27.1-alpine. If you vendor the binary, upgrading means tracking the CLI release. If you import the library, you are tracking the module version and its own compatibility guarantees, and the CLI release notes are not a substitute for reading those.
Licensing is Apache-2.0, the same licence as much of the Kubernetes ecosystem the project sits in, and the project has adopted the CNCF Code of Conduct. Apache-2.0 includes an explicit patent grant and requires that you preserve notices and state changes. That is a permissive arrangement, but it is not legal advice, and if you redistribute a modified ORAS CLI inside a product, the notice obligations are yours to satisfy.
One operational detail from the release process is worth copying into your own tagging scheme: the rolling-tag rules in the README prevent a backport release from dragging `:latest` backwards. If you mirror ORAS images into an internal registry, replicate that rule or you will eventually serve an older build to a client that asked for the newest one.
Editorial conclusion
Adopt ORAS CLI when your artifacts already live next to container images and you want one registry, one credential store and one retention policy for both. Skip it when your consumers expect a package manager or a plain HTTP file server, because a registry is not either of those. Before rolling it out, verify three things against your own registry: whether it accepts the artifact manifest media types your client sends, what garbage collection does to an untagged artifact, and whether your CI can authenticate without an interactive login.
Frequently asked questions
What does ORAS CLI mean?
ORAS stands for OCI Registry As Storage, and the CLI is a client for managing content such as artifacts, images and packages in an OCI-compliant registry. The project describes itself as an OCI registry client.
What is an OCI registry, and how does ORAS CLI use one?
An OCI registry is a content-addressed store that serves blobs and manifests addressed by digest, with tags as movable pointers to those digests. ORAS CLI pushes blobs and a manifest describing your artifact, then optionally attaches a tag so it can be pulled by name.
How do I install ORAS CLI on Linux?
The README does not include install steps and instead points to the project website at oras.land, where the CLI documentation is published under oras.land/cli. Release images are published to GitHub Container Registry at ghcr.io/oras-project/oras, and the Dockerfile shows how the binary is built from source with make.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/oras-project-oras)