Skip to main content
Skip to main content

Authoring Plugins

Create reusable libraries that others can install via argsh add.

Structure

A plugin is a directory with:

mylib/
├── argsh-plugin.yml # metadata (required)
├── mylib.sh # bash library (required)
├── mylib.bats # tests (recommended)
└── src/ # optional Rust builtin
├── Cargo.toml
└── lib.rs

Metadata

# argsh-plugin.yml
name: mylib
version: 0.1.0
description: What this library does
requires:
argsh: ">=0.9.0"
depends:
- jaml
- otherlib@0.2.0

Fields

FieldRequiredDescription
nameyesPlugin name. Must match [a-zA-Z0-9_-]+.
versionfor publishSemver version (x.y.z, optional -pre suffix). Required for argsh publish, optional otherwise.
descriptionnoShort description of the plugin.
requires.argshnoSemver constraint for the minimum argsh version (e.g. >=0.9.0). On argsh add, a warning is printed if the installed argsh does not satisfy the constraint.
dependsnoList of plugin dependencies. Each entry is a plugin name or name@version. Dependencies are auto-installed when the plugin is added via argsh add.

Library file

The main .sh file is what import mylib sources. Follow argsh conventions:

#!/usr/bin/env bash
# @file mylib
# @brief Short description
set -euo pipefail

# @description Do something useful.
# @arg $1 string Input value
# @stdout The result
mylib::do_thing() {
local input="${1}"
echo "processed: ${input}"
}

Testing

Write bats tests alongside the library:

#!/usr/bin/env bats

setup() {
source "${BATS_TEST_DIRNAME}/mylib.sh"
}

@test "mylib::do_thing works" {
result=$(mylib::do_thing "hello")
[[ "${result}" == "processed: hello" ]]
}

Run with:

bats mylib/mylib.bats

Publishing

Plugins are distributed as OCI artifacts via the arg-sh/libs repository. You can also publish to your own OCI registry.

Validation

argsh publish validates your argsh-plugin.yml before pushing:

  • name and version fields must be present.
  • name must match [a-zA-Z0-9_-]+.
  • version must be valid semver (x.y.z with optional -pre suffix). Tags like latest or bare integers are rejected.

Publishing to a registry

# Publish to the default registry (ghcr.io/arg-sh/libs)
argsh publish

# Publish to a custom registry
argsh publish --registry harbor.mycompany.com/argsh

Publishing requires the native builtin (.so) with OCI push support. Install it with argsh builtin install if missing.

Contributing to arg-sh/libs

  1. Fork github.com/arg-sh/libs
  2. Create your library directory with the structure above
  3. Add tests
  4. Submit a pull request

Optional: Rust builtins

For performance-critical operations, plugins can include a Rust builtin .so that provides native implementations of bash functions. See the libs repo for the workspace setup.

The .so is loaded automatically when available. The .sh file provides the pure-bash fallback.

Was this section helpful?