zhi plugins and workspaces can be shared via OCI-compatible container registries (GHCR, Docker Hub, Harbor, ECR, ACR, GAR, or any self-hosted OCI registry). This guide covers installing, publishing, searching, updating, and securing shared artifacts.
The zhi project publishes example plugins to the GitHub Container Registry. These are built, signed, and released automatically on every tagged release:
| Plugin | OCI Reference |
|---|---|
| zhi-config-pokedex | oci://ghcr.io/mrwong99/zhi/zhi-config-pokedex |
| zhi-transform-pokedex | oci://ghcr.io/mrwong99/zhi/zhi-transform-pokedex |
| zhi-store-json | oci://ghcr.io/mrwong99/zhi/zhi-store-json |
| zhi-store-memory | oci://ghcr.io/mrwong99/zhi/zhi-store-memory |
| zhi-store-vault | oci://ghcr.io/mrwong99/zhi/zhi-store-vault |
| zhi-ui-httpapi | oci://ghcr.io/mrwong99/zhi/zhi-ui-httpapi |
| zhi-ui-webui | oci://ghcr.io/mrwong99/zhi/zhi-ui-webui |
Install any of them with:
zhi plugin install oci://ghcr.io/mrwong99/zhi/zhi-store-memory:v0.0.9
All official plugins are signed with keyless cosign via Sigstore. No registry authentication is required to pull public plugins from GHCR.
Install a plugin from an OCI registry reference or a marketplace short name:
# From an OCI reference
zhi plugin install oci://ghcr.io/mrwong99/zhi/zhi-config-pokedex:v0.0.9
# From a marketplace short name (resolves via marketplace API)
zhi plugin install ansible-config
# Specific version
zhi plugin install ansible-config@1.2.0
Installed plugins are placed in ~/.zhi/plugins/ and are immediately available for use in zhi.yaml.
| Flag | Description |
|---|---|
--platform |
Override platform detection (e.g. linux/amd64) |
--force |
Overwrite existing plugin even if same version |
--skip-verify |
Skip signature verification (not recommended) |
To publish a plugin, create a zhi-plugin.yaml manifest in your project root:
schemaVersion: "1"
name: pokedex
type: config
version: 0.0.1
zhiProtocolVersion: "1"
description: The zhi example pokedex plugin
author: MrWong99
license: MIT
homepage: https://mrwong99.github.io/zhi/docs/plugin-development/overview.html
keywords:
- example
- config
- pokedex
# Build artifacts (paths relative to project root)
binaries:
linux/amd64: dist/zhi-config-pokedex
Generate a manifest interactively:
zhi plugin init --name my-config --type config --version 1.0.0
Build your binaries for each platform, then publish:
zhi plugin publish --registry ghcr.io/myorg
zhi plugin publish --registry ghcr.io/myorg --sign # sign with cosign
zhi plugin publish --registry ghcr.io/myorg --sign --key cosign.key # sign with key
| Flag | Description |
|---|---|
--registry |
Target OCI registry (required) |
--tag |
OCI tag (default: v{version} from manifest) |
--sign |
Sign the artifact with cosign after pushing |
--key |
Path to cosign private key (default: keyless via Fulcio/OIDC) |
Search the marketplace for plugins by name, type, or keywords:
zhi plugin search ansible
zhi plugin search "vault store" --type store
zhi plugin search --type ui --sort rating --verified
| Flag | Description |
|---|---|
--type |
Filter by plugin type (config, transform, store, ui) |
--sort |
Sort by: relevance, downloads, rating, updated |
--verified |
Show only verified plugins |
--json |
Output as JSON |
--limit |
Maximum results (default: 20) |
Get detailed information about a plugin:
zhi plugin info ansible-config
This shows the publisher, version, rating, download count, signing status, and whether an update is available.
Rate plugins on the marketplace (requires an API key in ~/.zhi/config.yaml):
zhi plugin rate zhi-project/ansible-config 5
zhi plugin rate zhi-project/ansible-config 4 --comment "Works well but missing docs"
Check for and install plugin updates:
zhi plugin update --check # Check for available updates
zhi plugin update --check --changelog # Show changelogs for available updates
zhi plugin update ansible-config # Update a specific plugin
zhi plugin update --all # Update all plugins
Pin a plugin to prevent automatic updates:
zhi plugin pin ansible-config # Pin at current version
zhi plugin unpin ansible-config # Allow updates again
Pinned plugins are skipped during zhi plugin update --all but can still be updated explicitly by name.
Restore a plugin to its previous version (the pre-update binary is kept as a backup):
zhi plugin rollback ansible-config
If no backup exists, install a specific version with zhi plugin install ansible-config@1.1.0 --force.
Plugins are signed using Sigstore (cosign) for artifact integrity and publisher identity:
# Verify a plugin's signature without installing
zhi plugin verify oci://ghcr.io/zhi-project/zhi-config-ansible:v1.2.0
| Level | Description |
|---|---|
None (--skip-verify) |
No signature check. Binary digest still verified against OCI manifest. |
| Signed (default) | Artifact has a valid cosign signature from any identity. |
| Verified publisher | Signer identity matches the registered marketplace publisher. |
Strict (requireSignatures: true) |
Only signed artifacts from trusted publishers can be installed. |
At launch time, zhi compares the plugin binary’s SHA-256 digest against the digest recorded during installation. A mismatch indicates post-install tampering and is logged as an error.
Configure ~/.zhi/policy.yaml to enforce security requirements:
requireSignatures: true
allowedRegistries:
- ghcr.io
- harbor.company.internal
trustedPublishers:
- zhi-project
- myorg
Trusted signing keys are managed in ~/.zhi/keys/.
Workspaces can be shared as OCI artifacts that bundle zhi.yaml, templates, apply scripts, and plugin dependency declarations.
zhi workspace install k8s-cluster
zhi workspace install oci://ghcr.io/org/zhi-workspace-k8s:v1.0 ./my-cluster
This pulls the workspace files, installs any declared plugin dependencies, and checks for required external tools.
| Flag | Description |
|---|---|
--skip-plugins |
Don’t install plugin dependencies |
--skip-tools-check |
Don’t check for required external tools |
--dry-run |
Show what would be installed |
zhi workspace publish --registry ghcr.io/myorg
zhi workspace publish --registry ghcr.io/myorg --sign
Generate a zhi-plugins.lock file that pins all plugin dependencies to exact OCI digests for reproducible builds:
zhi workspace lock # Lock current versions
zhi workspace lock --update # Update all plugins and re-lock
Lock files ensure CI/CD pipelines and team members install identical plugin versions.
Authenticate with OCI registries:
zhi registry login ghcr.io --username myuser
echo $GHCR_TOKEN | zhi registry login ghcr.io --username myuser --password-stdin
zhi registry logout ghcr.io
zhi registry list # List configured registries
Credentials are stored in ~/.zhi/config.yaml or delegated to Docker credential helpers.
The zhi-marketplace server supports TLS and mutual TLS (mTLS) using the same flags as zhi-mirror:
zhi-marketplace --listen :8443 \
--tls-cert /etc/zhi-marketplace/server.crt \
--tls-key /etc/zhi-marketplace/server.key \
--tls-min-version 1.3
For mTLS, add --tls-client-ca /path/to/client-ca.crt. See Enterprise Mirror for the full flag reference.
When connecting to registries or marketplace servers that require mutual TLS, configure client certificates and custom CAs in ~/.zhi/config.yaml.
Applied to all outbound connections (registries and marketplace):
tls:
certFile: /path/to/client.crt
keyFile: /path/to/client.key
caFile: /path/to/server-ca.crt
Override the global TLS settings for a specific registry:
registries:
mirror.company.internal:5050:
username: myuser
password: mytoken
tls:
certFile: /path/to/client.crt
keyFile: /path/to/client.key
caFile: /path/to/mirror-ca.crt
Per-registry TLS settings take precedence over the global tls section.
The zhi-mirror server can present client certificates when connecting to upstream registries that require mTLS:
zhi-mirror serve --listen :5050 \
--upstream-registry registry.internal \
--upstream-tls-cert /path/to/client.crt \
--upstream-tls-key /path/to/client.key \
--upstream-tls-ca /path/to/upstream-ca.crt
| Flag | Description |
|---|---|
--upstream-tls-cert |
Client certificate for upstream mTLS |
--upstream-tls-key |
Client key for upstream mTLS |
--upstream-tls-ca |
CA to verify upstream server certificate |
Configure sharing defaults in ~/.zhi/config.yaml:
default: ghcr.io
marketplace:
url: https://marketplace.zhi.dev
apiKey: zhk_abc123...
# Client TLS for mTLS connections (optional)
tls:
certFile: /path/to/client.crt
keyFile: /path/to/client.key
caFile: /path/to/ca.crt
# use the zhi registry login command to create this section
registries:
ghcr.io:
username: myuser
password: ghp_aRS...