Creating & Publishing Packages
A complete guide on how to create and publish a package for Zoi.
This guide provides a start-to-finish walkthrough of creating a new package, testing it locally, and publishing it to the official Zoi package repositories for everyone to use.
Understanding Zoi Repositories
Zoi organizes its packages into several repositories, each with a specific purpose. When you contribute a new package, you'll need to decide which repository is the best fit.
Repository | Description |
---|---|
core | Essential packages and libraries; very common and well-maintained. |
main | Important packages that don't fit in core but are essential for most users. |
extra | New or niche packages; less common and may be less actively maintained. |
community | User-submitted packages. New entries start here and may graduate to higher tiers. |
test | Testing ground for new Zoi features and packages prior to release. |
archive | Archived packages that are no longer maintained. |
For your first contribution, you will almost always be adding your package to the community
repository.
For more information about repositories visit here
Step 1: Creating Your pkg.yaml
File
The heart of every Zoi package is a pkg.yaml
file. This file contains all the metadata and instructions Zoi needs to install your software.
You can create this file manually, or use Zoi's interactive helper.
Option A: Using the Interactive make
Command (Recommended)
The easiest way to create a valid package file is with the zoi make
command. It launches an interactive terminal UI that guides you through filling out all the necessary fields.
# Launch the interactive creator
zoi make
# You can also pre-fill the package name
zoi make my-new-app
This will create a my-new-app.pkg.yaml
file in your current directory with all the correct formatting and even the JSON schema link for editor autocompletion.
Option B: Creating the File Manually
If you prefer to create the file by hand, here's what you need to know.
Using the JSON Schema for Validation
To help you create valid pkg.yaml
files and get autocompletion in supported editors (like VS Code), you can add a $schema
tag pointing to the official Zoi package schema.
# my-cli.pkg.yaml
# yaml-language-server: $schema=https://gitlab.com/Zillowe/Zillwen/Zusty/Zoi/-/raw/main/app/pkg.schema.json
name: my-cli
repo: community
# ... rest of your package definition
This line tells your editor to use the schema for validation, which can catch errors before you even test the package.
Basic Structure
At a minimum, your package needs these fields:
# my-cli.pkg.yaml
# yaml-language-server: $schema=https://gitlab.com/Zillowe/Zillwen/Zusty/Zoi/-/raw/main/app/pkg.schema.json
name: my-cli
repo: community
version: 1.2.3
description: A simple command-line utility.
website: https://example.com/my-cli
readme: https://example.com/my-cli/README.md
git: https://github.com/user/my-cli
maintainer:
name: "Your Name"
email: "[email protected]"
# Optional: URL to your public GPG key
key: "https://keys.example.com/your-key.gpg"
# (Optional) Website of the maintainer
website: "https://maintainer.com"
# Optional: if the package author is different
author:
name: "Original Author"
key: "https://keys.example.com/author-key.gpg"
license: MIT
name
: The unique identifier for your package.version
: The current version of the software. You can also set this to"{git}"
to automatically use the latest stable release tag from the GitHub or GitLab repository specified in thegit
field.description
: A short, one-sentence summary of what the package does.maintainer
: Your name, website and email.license
: The software's license. This should be a valid SPDX license expression (e.g,MIT
,GPL-3.0-or-later
,MIT OR Apache-2.0
). If the license is proprietary and not covered by an SPDX identifier, useProprietary
. Zoi will check if the license is OSI-approved and will show a warning if it's not.
It's also highly recommended to add:
website
: The official project website.git
: The URL of the source code repository.readme
: A URL to a README file (markdown or plain text).
Package Types
Zoi supports different types of packages. You can specify the type using the type
field.
package
(Default): A standard software package.collection
: A meta-package that only installs a list of other packages as dependencies.service
: A package that runs as a background service (e.g. a database). Can be managed with native system commands or with Docker Compose.config
: A package that manages configuration files for another application.app
: An application template used withzoi create <source> <appName>
to scaffold projects. Not installable directly.extension
: A package that can modify Zoi's configuration, such as adding new package repositories. It is not installed in the traditional sense but its changes are applied or reverted.library
: A software library, which can include headers, shared libraries (.so, .dll), and static libraries (.a). It can also generatepkg-config
files for easier integration with build systems.
Tags (Recommended)
Add a tags
list to improve discoverability in zoi search
and to let users filter by tags.
tags:
- cli
- devtools
- editor
Step 2: Defining an Installation Method
The installation
section tells Zoi how to get the software onto a user's machine. You can provide multiple methods, and Zoi will pick the best one for the user's platform.
binary
For downloading a single, pre-compiled executable.
installation:
- type: binary
url: "https://github.com/user/my-cli/releases/download/v{version}/my-cli-{platform}"
platforms: ["linux-amd64", "macos-amd64", "windows-amd64"]
For more complex installers or application bundles like .dmg
on macOS, .msi
on Windows, or .appimage
on Linux, you can add the binary_types
field. Zoi will then use platform-specific logic to handle the installation.
installation:
- type: binary
url: "https://github.com/user/my-gui-app/releases/download/v{version}/my-gui-app-{platform}"
platforms: ["macos-amd64", "windows-amd64", "linux-amd64"]
# (Optional) Specify installer/bundle types.
# Zoi will handle them appropriately (e.g. mount DMG, run MSI).
# Supported types: "dmg", "msi", "appimage"
binary_types: ["dmg", "msi", "appimage"]
com_binary
(Compressed Binary)
For downloading a .zip
or .tar.gz
archive that contains the binary.
installation:
- type: com_binary
url: "https://github.com/user/tool/releases/download/v{version}/tool-v{version}-{platform}.{platformComExt}"
platforms: ["linux-amd64", "macos-amd64", "windows-amd64"]
platformComExt:
linux: "tar.gz"
macos: "tar.gz"
windows: "zip"
# (Optional) Path or filename of the executable inside the archive.
# If this ends with .exe, Zoi installs it as <package>.exe; otherwise <package>.
# Can be a relative path (bin/tool) or just a filename (tool.exe).
# On Windows targets, if this does not end with .exe, Zoi will also try with .exe appended.
binary_path: "bin/tool"
Supported archive formats for com_binary
are documented in Supported Archives for Compressed Binaries.
source
For packages that need to be compiled from source code.
installation:
- type: source
url: "https://github.com/{git}" # {git} is a placeholder for the top-level git field
platforms: ["linux-amd64", "macos-amd64", "windows-amd64"]
# (Optional) One of these may be specified to pick a ref
# tag can include placeholders like v{version}
# tag: "v{version}"
# branch: "release/{version}"
commands:
- "make build"
- "mv ./bin/compiler {store}/compiler" # {store} is the path to Zoi's install directory
script
For tools that use an installation script (e.g. install.sh
).
installation:
- type: script
url: "https://example.com/install.{platformExt}" # {platformExt} becomes 'sh' or 'ps1'
platforms: ["linux-amd64", "macos-amd64", "windows-amd64"]
Placeholders
Zoi uses placeholders to make your URLs dynamic:
{version}
: The package version.{platform}
: The user's platform (e.g.linux-amd64
).{platformComExt}
: The correct compressed archive extension for the OS.{platformExt}
: The correct script extension for the OS.{git}
: The value of the top-levelgit
field.{store}
: The path where the final binary should be placed (forsource
builds).
For resolving a package version from a remote URL (plain text or JSON), see the example in Package with Remote Version URL.
Security: Checksums
It is highly recommended to include checksums to verify the integrity of downloaded files.
installation:
- type: binary
url: "..."
platforms: ["..."]
checksums:
# Option 1: URL to a checksums file (e.g. checksums.txt)
# Defaults to sha512 algorithm
url: "https://github.com/user/my-cli/releases/download/v{version}/checksums.txt"
# Option 2: Explicit list with algorithm type
# type: sha256 # or sha512 (default)
# list:
# - file: "my-cli-zip"
# # Hex digest or URL to a file containing the digest
# checksum: "<hex-digest-or-url>"
Security: Signatures
For an even higher level of security, you can add GPG signature verification. This ensures that the package was published by a trusted developer.
This requires two parts:
-
Provide a GPG Key: Add a
key
field to themaintainer
orauthor
sections. The value can be a URL pointing to the public GPG key, or the key's 40-character fingerprint. Zoi will fetch fingerprints fromkeys.openpgp.org
.maintainer: name: "Your Name" email: "[email protected]" # Can be a URL to the key, or the key's fingerprint key: "DEADC0DEDEADBEEFDEADC0DEDEADBEEFDEADC0DE" author: name: "Original Author" # A URL is also valid key: "https://keys.example.com/author-key.gpg"
-
Add Signature Information: In the
installation
method, add asigs
list. Each item specifies a file and a URL to its corresponding.sig
file.installation: - type: binary url: "..." platforms: ["..."] # ... checksums ... sigs: - file: "my-cli-{platform}" # The file to verify sig: "https://github.com/user/my-cli/releases/download/v{version}/my-cli-{platform}.sig" # URL to the signature
Zoi will download the key from the URL, import it, and use it to verify the signature of the downloaded file.
Step 3: Adding Dependencies
If your package requires other tools to be installed, define them in the dependencies
section. Dependencies are split between build
(needed to compile from source) and runtime
(needed to run the application).
Both build
and runtime
dependencies can be further divided into required
and optional
.
dependencies:
build:
required:
- native:make
- native:gcc
runtime:
required:
- zoi:some-base-library
optional:
- zoi:plugin-A:adds feature X
- zoi:plugin-B:adds feature Y
required
: Dependencies that are always installed.optional
: Dependencies that the user is prompted to install. The format ismanager:package-name:description
, where the description explains what the dependency provides.
Selectable Required Dependencies
For more complex scenarios, you can offer the user a choice between different providers for a required dependency. This is useful when your application supports multiple backends (e.g. different GUI toolkits or database drivers).
You can structure the required
section with an options
block:
dependencies:
runtime:
required:
# You can mix simple required dependencies...
- zoi:core-library
# ...with selectable options.
options:
- name: "GUI"
desc: "GUI Providers"
all: no # 'no' means the user must choose only one. 'yes' allows multiple selections.
depends:
- native:qt6:for KDE desktop environments
- native:gtk4:for GNOME-based desktop environments
When a user installs this package, Zoi will prompt them to choose a GUI provider, ensuring the necessary dependency is met while giving the user control.
These choices, along with any selected optional
dependencies, are automatically saved to a <package_name>.manifest.yaml
file in the package's store directory. This file can be shared to allow for fully reproducible, non-interactive installations of the package with the same dependency set.
Advanced: Full dependency schema
Both runtime
and build
support the same structure: a simple list, or an advanced object with required
, options
, and optional
all at once.
dependencies:
runtime:
required:
- zoi:core-utils
options:
- name: "GUI Toolkit"
desc: "Choose a GUI provider for the application"
all: false
depends:
- native:qt6:Recommended for KDE Plasma
- native:gtk4:Recommended for GNOME
- native:libadwaita:For a modern GNOME look and feel
optional:
- zoi:extra-utils:handy extras
build:
required:
- zoi:build-utils
options:
- name: "Build GUI Toolkit"
desc: "Choose GUI dev libraries"
all: true
depends:
- native:qt6-dev:KDE toolkit headers and libs
- native:gtk4-dev:GNOME toolkit headers and libs
optional:
- zoi:extra-build-utils:extra helpers
- Required entries cannot have inline descriptions. If you need description and choice, use an
options
group. - Optional entries can have inline descriptions using
manager:package:description
. - In an
options
group, eachdepends
item can include an inline description after the second:
. - During installation:
- For normal packages,
build
dependencies are installed when a source build is selected/required (no compatiblebinary
/com_binary
), or when forcing source. - For
collection
andconfig
packages, bothruntime
andbuild
dependencies are honored directly.
- For normal packages,
Step 4: Adding Post-Installation & Uninstallation Hooks
Some packages may require additional setup steps after installation is complete, or cleanup steps during uninstallation. The post_install
and post_uninstall
fields allow you to define platform-specific commands.
Zoi will ask for user confirmation before running these commands for security.
post_install
These commands run after a successful installation. This is useful for setting up shell completions or running a configuration wizard.
post_install:
- platforms: ["linux", "macos"]
commands:
- "echo 'Heads up! {name} needs to do some post-install setup.'"
- "{name} --setup-completions"
- platforms: ["windows"]
commands:
- "echo 'Successfully installed {name} v{version}!'"
platforms
: A list of platforms where these commands should run (e.g.linux
,macos
,windows
,linux-amd64
).commands
: A list of shell commands to execute. You can use the{name}
and{version}
placeholders.
post_uninstall
These commands run before a package is uninstalled. This is useful for cleaning up configuration files, removing system services, or deregistering components.
post_uninstall:
- platforms: ["linux", "macos"]
commands:
- "echo 'Running cleanup tasks for {name}...'"
- "{name} --remove-completions"
The structure is identical to post_install
.
Step 5: Creating a Collection Package
A collection
is a meta-package that doesn't install any files itself but instead groups other packages together as dependencies. This is useful for creating "bundles" of tools, like a complete development environment for a specific language or framework.
To create a collection, set the type
field to collection
and list the packages you want to include in the dependencies
section.
# collections/web-dev-essentials.pkg.yaml
name: web-dev-essentials
repo: community
type: collection # Set the package type to 'collection'.
version: "1.0"
description: "A collection of essential tools for web development."
tags: [collection, web, devtools]
maintainer:
name: "Community"
email: "[email protected]"
# The 'runtime' dependencies are the packages that will be installed.
# This collection demonstrates pulling tools from different package managers.
dependencies:
runtime:
required:
- zoi:node
- zoi:bun
- native:git
optional:
- npm:pnpm
- npm:serve
- npm:typescript
When a user runs zoi install web-dev-essentials
, Zoi will install node
, bun
, and git
, and then prompt the user to install the optional packages.
Step 6: Creating a Config Package
A config
package is designed to manage configuration files for another application. It doesn't install an executable itself, but it can run scripts to place or remove configuration files. It's a good practice to make the config package depend on the application it configures.
To create a config package, set the type
to config
and define a config
block with install
and uninstall
commands.
The config
field
This field contains platform-specific commands to manage the configuration files.
# my-app-config.pkg.yaml
name: my-app-config
repo: community
type: config
version: "1.0"
description: "Configuration files for my-app."
# ... other metadata ...
dependencies:
runtime:
required:
- zoi:my-app # This config depends on 'my-app' being installed.
config:
- platforms: ["linux", "macos"]
# These commands are run to place the config files.
# Assume your package repo includes a 'config.toml' file.
install:
- "mkdir -p ~/.config/my-app"
- "cp ./config.toml ~/.config/my-app/config.toml"
# These commands are run when the user uninstalls the config.
uninstall:
- "rm ~/.config/my-app/config.toml"
When a user installs this package, Zoi will first ensure my-app
is installed, and then ask for confirmation before running the install
commands. When uninstalled, it will run the uninstall
commands.
Step 7: Creating an App Template
An app
package is a template used to scaffold new applications with the zoi create <source> <appName>
command. It is not installable directly like other packages. This is useful for creating starter projects for frameworks like Rails, React, or your own custom project structure.
To create an app template, set the type
to app
and define an app
block.
The app
field
This field contains the commands needed to create the new application.
# apps/rails-app.pkg.yaml
name: rails-app
repo: community
type: app
version: "7"
description: "Rails app template"
# ... other metadata ...
dependencies:
runtime:
required:
- zoi:@core/ruby
- zoi:@main/gems/rails
# Platform-specific create command and optional follow-up commands
app:
- platforms: ["all"]
appCreate: "rails new ${appName}"
commands:
- "cd ${appName} && bundle install"
- "cd ${appName} && git init"
Key fields:
type: app
: Declares the package as an app template.app.appCreate
: The main command to run to create the project. The${appName}
placeholder will be replaced with the name the user provides.app.commands
: An optional list of follow-up commands to run after the project is created.dependencies
: Any dependencies listed underruntime
orbuild
will be installed before theappCreate
command is run.
To use this template, a user would run:
zoi create rails-app MyNewBlog
Step 8: Creating a Service Package
A service
is a package type for applications that run in the background, like databases or web servers. Zoi can manage starting and stopping these services.
You can define a service to be run via native system commands or with Docker Compose.
Command-Based Service
This is for services managed by shell commands.
# my-service.pkg.yaml
type: service
# ...
service:
- platforms: ["linux", "macos"]
start:
- "my-service --daemon"
stop:
- "pkill my-service"
Docker-based Service
If your service is defined in a docker-compose.yml
file, Zoi can manage it for you.
# my-docker-service.pkg.yaml
type: service
# ...
service:
- platforms: ["all"] # Or specific platforms
docker:
- type: compose
file: "https://example.com/my-service/docker-compose.yml"
Key fields:
docker
: A list of docker service definitions.type: compose
: Specifies that this is a Docker Compose service.file
: A URL to thedocker-compose.yml
file. Zoi will download this file, store it, and use it to start and stop the service withdocker-compose up -d
anddocker-compose down
.
When a user installs a service package, Zoi will ask if they want to start it. They can also manage it later with zoi start <pkg>
and zoi stop <pkg>
.
Step 9: Creating an Extension
An extension
is a special package type that doesn't install software but instead modifies Zoi's own configuration. This is useful for distributing sets of repositories or other configuration changes as a single package.
To create an extension, set the type
field to extension
and define an extension
block.
The extension
field
This field contains the configuration changes to be applied.
# my-repo-extension.pkg.yaml
name: my-repo-extension
repo: community
type: extension
version: "1.0"
description: "Adds my custom repositories to Zoi."
# ... other metadata ...
extension:
type: zoi # Required. Currently, only 'zoi' is supported.
changes:
# A list of changes to apply when the extension is added.
# These changes are reverted when the extension is removed.
- type: repo-git
add: https://github.com/user/my-cool-pkgs.git
- type: repo-add
add: community
- type: registry-repo
add: https://my-mirror.com/Zoi-Pkgs.git
Key Fields:
type: extension
: Declares the package as an extension.extension.type
: The type of extension. Currently, onlyzoi
is a valid value.extension.changes
: A list of changes to make. Each change has atype
and anadd
value.
Change Types:
repo-git
: Clones a git repository into Zoi's package sources. Theadd
value should be a valid git repository URL. This allows users to install packages from your git repo using@git/<repo-name>/<pkg-name>
.repo-add
: Adds an official repository (e.g.community
,test
) to the list of active repositories that Zoi searches.registry-repo
: Changes the URL of the main package database registry that Zoi syncs with.
Installing and Removing Extensions
Extensions are managed with the zoi extension
subcommand.
# Add the extension and apply its changes
zoi extension add my-repo-extension
# Remove the extension and revert its changes
zoi extension remove my-repo-extension
This makes it easy to share and manage complex Zoi configurations.
Step 10: Creating a Library Package
A library
is a package that provides shared objects (.so
), dynamic-link libraries (.dll
), static archives (.a
), and header files for other software to use. Zoi can install these files to the correct system locations and generate pkg-config
files (.pc
) to make them discoverable by build systems like make
.
To create a library, set the type
to library
and provide a pkg_config
block.
The pkg_config
field
This field contains the information needed to generate a .pc
file.
# my-library.pkg.yaml
name: my-library
repo: community
type: library
version: 1.0.0
description: "A cool library that does things."
# ... other metadata ...
# This block is used to generate the .pc file
pkg_config:
description: "A cool library"
libs: "-lmy-library"
cflags: "-I/some/extra/path"
installation:
- type: com_binary
url: "https://example.com/my-library-v{version}-{platform}.tar.gz"
platforms: ["linux-amd64"]
# Zoi will look for .so, .a, and .h files in the archive
# and install them to the correct locations.
Key Fields:
type: library
: Declares the package as a library.pkg_config
: A block containing metadata for the.pc
file.description
: A short description for thepkg-config
file.libs
: The linker flags required to use the library (e.g.-lmy-library
).cflags
: The compiler flags required to use the library (e.g.-I/path/to/headers
).
Installation of Library Files
When a library
package is installed, Zoi handles the files as follows:
- Shared/Static Libraries (
.so
,.dll
,.a
,.lib
): These are installed into the system's library directory (/usr/local/lib
on Linux,~/.local/lib
for user-scoped installs). - Header Files (
.h
,.hpp
): These are installed into the system's include directory (/usr/local/include
on Linux,~/.local/include
for user-scoped installs). pkg-config
File: A.pc
file is generated and installed to the appropriatepkgconfig
directory, making the library discoverable withpkg-config --cflags --libs my-library
.
For source
installations of libraries, you can use the {prefix}
placeholder in your build commands, which will resolve to the correct installation root (e.g. /usr/local
or ~/.local
).
installation:
- type: source
url: "{git}"
commands:
- "./configure --prefix={prefix}"
- "make"
- "make install"
This allows standard build systems to install the library files into the correct locations that Zoi manages.
Advanced pkg.yaml
Features
Beyond the basics, pkg.yaml
offers powerful fields for more complex scenarios like package aliasing and defining specific update behaviors.
The alt
Field: Aliasing and Redirection
The alt
field allows you to redirect Zoi to resolve a different package source. This is incredibly useful for creating aliases or maintaining multiple versions of a package. When a user tries to install the current package, Zoi will instead fetch and install the one specified in the alt
field.
The value of alt
can be:
- Another package name (e.g.
my-app-git
). - A URL to a raw
.pkg.yaml
file. - A local file path to a
.pkg.yaml
file.
Use Case: Creating a "latest" alias
Imagine you have a package my-app
that is built from source, but you also want to provide a pre-compiled version for users who don't want to build it. You can create two package files:
my-app-bin.pkg.yaml
: Installs the pre-compiled binary.my-app.pkg.yaml
: An alias that points to the binary version.
# my-app.pkg.yaml
name: my-app
repo: community
version: 1.0.0
description: A simple command-line utility (alias for binary).
# ... other metadata ...
alt: my-app-bin # Redirects to the 'my-app-bin' package
Now, when a user runs zoi install my-app
, Zoi will automatically resolve and install my-app-bin
instead.
The updater
Field: Custom Update Logic
The updater
field gives you control over how zoi update
behaves for your package. By default, Zoi will try to find a binary
or com_binary
to perform an update. However, you can force it to use a different method.
The value of updater
can be one of the installation types: binary
, com_binary
, script
, or source
.
Use Case: Forcing a source build on update
If your package must always be compiled from the latest source code to function correctly, you can ensure that zoi update
always pulls and rebuilds it.
# my-compiler.pkg.yaml
name: my-compiler
repo: community
version: 0.2.0
description: A compiler that needs to be built from the latest source.
# ...
updater: source # Force 'zoi update' to use the 'source' method
installation:
- type: source
url: "https://github.com/{git}"
commands:
- "make clean"
- "make build"
- "mv ./bin/compiler {store}/compiler"
- type: binary
# This binary is provided as an initial install option,
# but updates will always use the source method above.
url: "https://github.com/user/compiler/releases/download/v{version}/compiler-{platform}"
platforms: ["linux-amd64", "macos-amd64"]
In this example, a user can get a pre-compiled binary on their first zoi install
, but every subsequent zoi update my-compiler
will trigger a fresh build from the source repository, ensuring they always have the latest version.
The rollback
Field: Disabling Backups
By default, Zoi creates a backup of a package before upgrading it, allowing users to revert to the previous version with zoi rollback
. You can disable this behavior for your package by setting the rollback
field to false
.
Use Case: Volatile or Large Packages
If your package is very large, or if its state is managed externally and backups are not useful, you can prevent Zoi from creating them.
# my-large-asset-pack.pkg.yaml
name: my-large-asset-pack
# ...
rollback: false # Zoi will not create a backup of this package on upgrade
The updates
Field: Important Update Messages
You can add an updates
section to your pkg.yaml
to show important messages to the user before they install or update a package. This is useful for communicating breaking changes, security vulnerabilities, or other critical information.
The user will be shown these messages and prompted to continue with the installation.
# my-package.pkg.yaml
name: my-package
version: 2.0.0
# ...
updates:
- type: change
message: "This version introduces a new configuration file format. Please see the migration guide."
- type: vulnerability
message: "A critical vulnerability (CVE-2025-12345) is present in this version. It is recommended to wait for the next release."
- type: update
message: "This package will no longer be maintained after 2026."
Update Types:
change
: For breaking changes or important modifications.vulnerability
: For security-related warnings.update
: For general updates or announcements.
Handling Conflicts: bins
and conflicts
To prevent issues where two different packages provide the same command-line tool or are otherwise incompatible, Zoi offers two fields to manage conflicts. If a conflict is detected, Zoi will warn the user and ask for confirmation before proceeding with the installation.
If these fields are not present, Zoi falls back to its default behavior of checking if a command with the same name as the package already exists on the system.
The conflicts
Field
This field lets you declare that your package is incompatible with a list of other Zoi packages.
# my-new-editor.pkg.yaml
name: my-new-editor
version: 1.0.0
# ...
conflicts:
- old-editor # This package cannot be installed if 'old-editor' is present
- another-editor
The bins
Field
This field lists the executable files (binaries) that your package installs. Zoi uses this to detect if another installed package provides a binary with the same name.
# my-utils.pkg.yaml
name: my-utils
version: 1.0.0
# ...
# This package installs two commands: 'mu' and 'mu-helper'
bins:
- mu
- mu-helper
If a user tries to install my-utils
while another package that also provides a mu
binary is already installed, Zoi will detect the conflict. This is different from the package name; for example, the vim
package might provide the vi
binary, which could conflict with a separate vi
package.
Step 11: Testing Your Package Locally
Before you publish your package, you must test it locally to ensure it installs correctly.
-
Save your
my-package.pkg.yaml
file somewhere on your machine. -
Run the install command, pointing to your local file:
zoi install ./path/to/my-package.pkg.yaml
If you are testing a
source
build, use thebuild
command:zoi build ./path/to/my-package.pkg.yaml
-
Zoi will attempt to install it just like a user would. Watch for any errors in the output.
-
After a successful installation, try running the command to make sure it works.
-
Finally, uninstall it to ensure a clean removal:
zoi uninstall my-package
Step 12: Publishing Your Package
Once your package works locally, it's time to share it with the world! This is done by adding your pkg.yaml
file to the official Zoi packages database.
The Zoi package database is hosted on GitLab and mirrored on GitHub and Codeberg.
- GitLab (Primary): Zillowe/Zillwen/Zusty/Zoi-Pkgs
- GitHub (Mirror): Zillowe/Zoi-Pkgs
- Codeberg (Mirror): Zillowe/Zoi-Pkgs
You can contribute by opening a Merge/Pull Request to either repository, or by opening an issue to request a new package. The following steps outline the process for creating a Merge Request on GitLab, which is very similar to the process on GitHub.
-
Fork the Repository: Go to the repository's page on GitLab or GitHub and click the "Fork" button to create your own copy.
-
Clone Your Fork: Clone the repository to your local machine.
# For GitLab git clone https://gitlab.com/YourUsername/Zoi-pkgs.git cd Zoi-pkgs
-
Choose the Right Directory: As discussed in the first section, you should almost always add new packages to the
community
directory.You can also create nested directories to better organize packages. For example, you could place a Linux-specific editor in
community/editors/linux/my-editor.pkg.yaml
. Therepo
field in your package file should then becommunity/editors/linux
. -
Add Your Package File: Copy your
my-package.pkg.yaml
file into thecommunity/
directory.cp /path/to/my-package.pkg.yaml community/
For a nested repository, create the directory structure and place your file inside:
mkdir -p community/editors/linux cp /path/to/my-editor.pkg.yaml community/editors/linux/
-
Commit and Push: Commit your new package file to your forked repository.
git add community/my-package.pkg.yaml git commit -m "feat(community): add my-package v1.2.3" git push origin main
For a nested package, your commit might look like this:
git add community/editors/linux/my-editor.pkg.yaml git commit -m "feat(community): add my-editor v1.0.0" git push origin main
-
Open a Merge/Pull Request: Go to your forked repository on GitLab or GitHub. You should see a button to "Create merge request" or "Create pull request". Click it.
- Title: Use a conventional commit message like
feat(community): add my-package
. - Description: Briefly describe what your package does and link to its official website or source code.
- Submit the request.
- Title: Use a conventional commit message like
A Zoi maintainer will review your submission. They may suggest some changes. Once approved, it will be merged, and your package will be available to everyone after the next zoi sync
!
Creating Your Own Git-Based Package Repository
While contributing to the official repositories is great for public packages, you might want to manage your own set of packages for private projects, company-internal tools, or personal use. Zoi makes this easy by allowing you to add any git repository as a package source.
Step 1: Create Your Git Repository
-
Create a new, empty repository on a service like GitLab or GitHub.
-
Add your
*.pkg.yaml
files to the root of the repository. The structure is simple: just a flat collection of package files.my-zoi-repo/ ├── my-first-package.pkg.yaml └── my-second-package.pkg.yaml
-
Commit and push your files to the remote repository.
Step 2: Add Your Repository to Zoi
Use the zoi repo add
command with your repository's HTTPS or SSH URL. Zoi will clone it locally.
zoi repo add https://github.com/YourUsername/my-zoi-repo.git
Zoi clones the repo into ~/.zoi/pkgs/git/
. The name of the repository is determined from the URL (e.g. my-zoi-repo
).
Step 3: Install Packages from Your Repository
To install a package from your custom git repository, use the @git/
prefix, followed by the repository name and the package name.
# To install my-first-package from the example above
zoi install @git/my-zoi-repo/my-first-package
This allows you to maintain and version your own collections of packages completely independently from the official Zoi databases.
Last updated on