Use when creating or modifying Justfiles in this repository, when adding new recipes, or when organizing just commands
60
49%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Advisory
Suggest reviewing before use
Optimize this skill with Tessl
npx tessl skill review --optimize ./.opencode/skills/writing-justfiles/SKILL.mdAll Justfiles in this repository follow bluefin-lts style patterns for consistency, discoverability, and maintainability.
Core principle: Export environment variables, use group decorators, favor composition over complexity.
| Element | Pattern | Example |
|---|---|---|
| Variables | export VAR := env("VAR", "default") | export image_name := env("BUILD_IMAGE_NAME", "egg") |
| Default recipe | @just --list | First recipe in file |
| Groups | [group('category')] | [group('build')] |
| Quiet mode | Prefix with @ | @just --list |
| Shell | #!/usr/bin/env bash + set -euo pipefail | Standard for all recipes |
| Comments | Brief description above recipe | # Build the OCI image |
Always use export for variables:
# ✅ GOOD: Exported with env() fallback
export image_name := env("BUILD_IMAGE_NAME", "egg")
export image_tag := env("BUILD_IMAGE_TAG", "latest")
# ❌ BAD: Not exported
image_name := "egg"
# ❌ BAD: No default value
export image_tag := env("BUILD_IMAGE_TAG")Why export:
Use env() with defaults:
env("VAR", "default") over bare assignmentsUse [group('category')] decorators on ALL recipes:
Standard categories:
info - Information commands (default, help)build - Build operations (build, export, clean)test - Testing operations (generate-bootable-image, boot-vm)dev - Development tools (bst, bootc)registry - Registry operations (if applicable)vm - VM operations (if applicable)# ✅ GOOD: Grouped and discoverable
[group('build')]
build:
just bst build oci/bluefin.bst
[group('test')]
boot-vm:
qemu-system-x86_64 ...
# ❌ BAD: No group decorator
build:
just bst build oci/bluefin.bstOrder recipes by logical workflow, not alphabetically:
First recipe should be @just --list:
# List available commands
[group('info')]
default:
@just --listWhy:
just with no args shows all available commandsUse quiet mode with @ prefix:
# ✅ GOOD: Suppresses command echo
[group('build')]
build:
@echo "Building..."
@just bst build oci/bluefin.bst
# ❌ BAD: Shows every command
[group('build')]
build:
echo "Building..."
just bst build oci/bluefin.bstSet shell options:
[group('build')]
build:
#!/usr/bin/env bash
set -euo pipefail
echo "Building OCI image..."
just bst build oci/bluefin.bstWhy these options:
-e - Exit on error (fail fast)-u - Error on undefined variables-o pipefail - Catch pipe failuresKeep recipes focused:
# ✅ GOOD: One task per recipe, compose with dependencies
[group('build')]
build:
just bst build oci/bluefin.bst
just export
[group('build')]
export:
just bst artifact checkout oci/bluefin.bst --directory .build-out
# ❌ BAD: Monolithic recipe doing too much
[group('build')]
build:
# Build + export + validate + publish all in one
...50 lines...Composition patterns:
deploy: build testjust buildAdd brief description above each recipe:
# Build the OCI image and load it into podman
[group('build')]
build:
...
# Boot the raw disk image in QEMU with UEFI (OVMF)
# Requires: qemu-system-x86_64, OVMF firmware, KVM access
[group('test')]
boot-vm:
...Explain non-obvious environment variables:
# VM settings
export vm_ram := env("VM_RAM", "8192")
export vm_cpus := env("VM_CPUS", "4")
# OCI metadata (dynamic labels)
export OCI_IMAGE_CREATED := env("OCI_IMAGE_CREATED", "")
export OCI_IMAGE_REVISION := env("OCI_IMAGE_REVISION", "")Document prerequisites for complex recipes:
# Boot the raw disk image in QEMU with UEFI (OVMF)
# Requires: qemu-system-x86_64, OVMF firmware, KVM access
[group('test')]
boot-vm:
...Conditional execution:
[group('build')]
export:
#!/usr/bin/env bash
set -euo pipefail
# Use sudo unless already root (CI runners are root)
SUDO_CMD=""
if [ "$(id -u)" -ne 0 ]; then
SUDO_CMD="sudo"
fi
$SUDO_CMD podman imagesFile existence checks:
[group('test')]
generate-bootable-image:
#!/usr/bin/env bash
set -euo pipefail
if ! sudo podman image exists "{{image_name}}:{{image_tag}}"; then
echo "ERROR: Image not found. Run 'just build' first." >&2
exit 1
fiPath detection loops:
[group('test')]
boot-vm:
#!/usr/bin/env bash
set -euo pipefail
OVMF_CODE=""
for candidate in \
/usr/share/edk2/ovmf/OVMF_CODE.fd \
/usr/share/OVMF/OVMF_CODE.fd; do
if [ -f "$candidate" ]; then
OVMF_CODE="$candidate"
break
fi
done| Mistake | Fix |
|---|---|
| Bare variable assignment | Use export VAR := env("VAR", "default") |
| No group decorators | Add [group('category')] to all recipes |
| Alphabetical ordering | Order by logical workflow |
| Echo command output | Prefix with @ for quiet mode |
| No shell options | Add set -euo pipefail |
| Monolithic recipes | Break into focused, composable recipes |
| Missing comments | Add brief description above each recipe |
| No default recipe | First recipe should be @just --list |
Wrapper pattern for bst commands:
# Runs any bst command inside the bst2 container via podman
[group('dev')]
bst *ARGS:
#!/usr/bin/env bash
set -euo pipefail
mkdir -p "${HOME}/.cache/buildstream"
podman run --rm \
--privileged \
--device /dev/fuse \
-v "{{justfile_directory()}}:/src:rw" \
-v "${HOME}/.cache/buildstream:/root/.cache/buildstream:rw" \
-w /src \
"{{bst2_image}}" \
bash -c 'bst --colors "$@"' -- ${BST_FLAGS:-} {{ARGS}}Why this pattern:
BST_FLAGS env varFrom this repository's Justfile:
# List available commands
[group('info')]
default:
@just --list
export image_name := env("BUILD_IMAGE_NAME", "egg")
export image_tag := env("BUILD_IMAGE_TAG", "latest")
# Build the OCI image and load it into podman
[group('build')]
build:
#!/usr/bin/env bash
set -euo pipefail
echo "==> Building OCI image..."
just bst build oci/bluefin.bst
just export
# Remove generated artifacts
[group('build')]
clean:
rm -f bootable.raw .ovmf-vars.fd
rm -rf .build-outThis demonstrates:
@build calls export)f062bf8
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.