Create & Contribute Packages¶
Use a package when a widget or Lua library should be installed, versioned, tested, and updated
independently from a user's manual widgets_dir.
EasyBarKit defines the package format used by both EasyBar frontends. The same manifest applies whether you publish a package from your own repository or contribute it to the official widgets repository.
Choose your path¶
| Goal | Workflow |
|---|---|
| Publish and maintain your own package | Start from the EasyBar widget template, publish releases from your repository, and optionally submit the package to the registry. |
| Contribute to the official package collection | Fork the official widgets repository, make the package change on a branch, and open a pull request against easybar-app/widgets:main. Maintainers publish the package release after merge. |
The package manifest and validation rules below apply to both paths.
Package layout¶
In the official widgets repository, a typical widget package contains:
packages/<name>/
├── package.toml
├── README.md
├── widget.lua
├── assets/
└── tests/
└── test.lua
Only include directories the package needs. Tests live under tests/ and are excluded from release
archives by the official widgets release tooling.
A package name should be lowercase and hyphen-separated.
For a standalone package repository, use the current layout from the widget template rather than copying the official monorepo directory structure unnecessarily.
Manifest contract¶
The current package contract is manifest version 2. EasyBarKit does not accept manifest version 1 and does not recognize the former EasyBar-specific minimum-version field.
Every package declares the minimum EasyBarKit version it requires:
manifest_version = 2
minimum_easybar_kit_version = "0.1.0"
The package manager compares that value with its EasyBarKit build version before activation. A package that requires a newer kit is rejected instead of being started with an unsupported API.
Widget manifest¶
A widget declares its entrypoint explicitly. The entrypoint is not required to be named
widget.lua; it may be any validated Lua path inside the package.
manifest_version = 2
name = "my-widget"
version = "0.1.0"
kind = "widget"
description = "Describe what the widget shows or controls."
license = "Apache-2.0"
minimum_easybar_kit_version = "0.1.0"
entrypoint = "widget.lua"
readme = "README.md"
categories = ["utilities"]
[repository]
url = "https://github.com/easybar-app/widgets"
path = "packages/my-widget"
The package manager activates exactly the declared entrypoint. It does not recursively discover other Lua files in the package.
Keep widget-owned assets inside the package and resolve them from the entrypoint with
easybar.asset(...):
local icon = easybar.asset("assets/icon.svg")
For managed packages, @/ resolves from the committed package root when package-root-relative access
is intentional.
Library manifest¶
A reusable library sets kind = "library", omits entrypoint, and declares its public modules:
manifest_version = 2
name = "my-library"
version = "1.0.0"
kind = "library"
description = "Reusable helpers for EasyBar widgets."
license = "Apache-2.0"
minimum_easybar_kit_version = "0.1.0"
readme = "README.md"
categories = ["library"]
[repository]
url = "https://github.com/easybar-app/widgets"
path = "packages/my-library"
[exports]
my_library = "my_library.lua"
Consumers load an export through normal Lua module resolution:
local library = require("my_library")
Export names may be namespaced. For example:
[exports]
"my_widget.policy" = "policy.lua"
Every non-test Lua file in an installable package must be either the widget entrypoint or a declared export. This keeps executable package files explicit.
Dependencies¶
Declare package dependencies with exact or caret semantic-version constraints:
[dependencies]
shared = "^0.1.0"
my-library = "^1.0.0"
The package manager resolves compatible installed versions first and uses the selected registry when it needs another release. The official widgets CI also checks that the current official package set does not require mutually incompatible versions of the same library.
Requirements and settings¶
Declare external commands, optional environment variables, native-inbox use, and user-facing
settings in package.toml when the package needs them. Existing official package manifests are the
best source for the optional table shapes, and the generated Catalog exposes the
resulting metadata.
The package README should explain:
- what the package does;
- whether it works in EasyBar, EasyBar Native, or both;
- required external tools and authentication;
- permissions;
- widget settings;
- important operational behavior.
Do not include credentials or machine-specific secrets.
Document frontend compatibility¶
Prefer the shared Lua API so a widget works in both frontends. A package README should explicitly identify any dependency on:
- the
easybaroreasybar-nativeexecutable; - EasyBar's Calendar or Network helper agents;
- a regular EasyBar native built-in, native group, or full-width layout behavior;
- a frontend-specific path that is not resolved from the runtime environment.
Inbox is available in both frontends, so using the shared native Inbox API does not by itself make a package EasyBar-only. EasyBar Native still exposes no other regular built-in widget surface.
Do not hard-code ~/.config/easybar, ~/.local/share/easybar, or
~/.local/state/easybar in a portable package. Use EasyBarKit APIs and the frontend-provided
environment instead. When a package intentionally invokes one frontend's CLI, declare that command
under [requirements] and document the restriction.
Tests¶
Put focused Lua tests in packages/<name>/tests/ when contributing to the official widgets
repository. The repository provides shared host implementations under tests/support/ and also runs
a cross-package smoke test.
From the widgets repository, with EasyBarKit available as a sibling checkout:
make check
make package PACKAGE=my-widget OUTPUT_DIR=dist
Use EASYBAR_KIT_ROOT=/path/to/easybar-kit with make check when the kit checkout is elsewhere.
Inspecting the generated archive before review is optional but useful.
Standalone package repositories should use the equivalent checks and release targets supplied by the widget template.
Publish your own package¶
For a package you maintain in your own repository:
- validate the package with the widget-template workflow;
- build a deterministic
<name>-<version>.tar.gzarchive; - publish the archive and its SHA-256 checksum as release assets;
- add or update the corresponding registry entry if the package should be discoverable through the Widget Store.
Published release archives are immutable. Publish a new semantic version for every package change.
Contribute to the official widgets repository¶
For an official package change:
- update the package source and
package.tomlunderpackages/<name>/; - increment the package version;
- run
make checkwith a compatible EasyBarKit checkout; - open a pull request;
- after merge, publish the package release through the repository release workflow.
The registry synchronizes published release metadata and checksums. A source version may therefore be ahead of the registry briefly between merge and release; installs continue to use the latest published registry version until the new release is synchronized.