ujust - User-facing Just Commands
This directory contains Just recipe files that will be installed into your custom image and made available to end users via the ujust command.
What is ujust?
ujust is a command that allows users to run predefined tasks on their system. It's built on top of just, a command runner similar to make but designed for commands rather than builds.
How It Works
- During Build: All
.justfiles in this directory are consolidated and copied to/usr/share/ublue-os/just/60-custom.justin the image - After Installation: Users run
ujustto see available commands - User Experience: Simple command interface for system tasks
File Structure
Create .just files in this directory with your custom commands:
custom/ujust/
├── README.md # This file
├── custom-apps.just # Application installation commands
└── custom-system.just # System configuration commands
Example Files in this directory:
custom-apps.just- Application installation commands (Brewfiles, Flatpaks, JetBrains Toolbox)custom-system.just- System configuration commands (benchmarks, dev groups, maintenance)
Example Commands
Basic Command
# Run a system maintenance task
run-maintenance:
echo "Running maintenance..."
sudo systemctl restart some-service
Interactive Command with gum
# Configure system setting
configure-thing:
#!/usr/bin/bash
source /usr/lib/ujust/ujust.sh
echo "Configure thing?"
OPTION=$(Choose "Enable" "Disable")
if [[ "${OPTION,,}" =~ ^enable ]]; then
echo "Enabling..."
# your enable logic
else
echo "Disabling..."
# your disable logic
fi
Command with Group
# Groups organize commands in ujust help
[group('Apps')]
install-brewfile:
brew bundle --file /usr/share/ublue-os/homebrew/development.Brewfile
Best Practices
Naming Conventions
- Use lowercase with hyphens:
install-something - Use verb prefixes for clarity:
install-- Install somethingconfigure-- Configure something pre-installedsetup-- Install + configuretoggle-- Enable/disable a featurefix-- Apply a fix or workaround
Command Structure
# Brief description of what the command does
[group('Category')]
command-name:
#!/usr/bin/bash
# Use bash shebang for multi-line scripts
# Commands go here
Error Handling
install-something:
#!/usr/bin/bash
set -euo pipefail # Exit on error, undefined vars, pipe failures
# Your commands
User Prompts
Use gum for interactive prompts (included in Universal Blue images):
interactive-command:
#!/usr/bin/bash
source /usr/lib/ujust/ujust.sh # Provides Choose() and other helpers
OPTION=$(Choose "Option 1" "Option 2" "Cancel")
echo "You chose: $OPTION"
Common Use Cases
1. Installing Software via Brewfiles
[group('Apps')]
install-dev-tools:
brew bundle --file /usr/share/ublue-os/homebrew/development.Brewfile
See examples in custom-apps.just for Brewfile shortcuts.
2. System Configuration
[group('System')]
configure-firewall:
#!/usr/bin/bash
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
See examples in custom-system.just for system configuration.
3. Development Environment Setup
[group('Development')]
setup-nodejs:
#!/usr/bin/bash
curl -fsSL https://fnm.vercel.app/install | bash
source ~/.bashrc
fnm install --lts
4. Maintenance Tasks
[group('Maintenance')]
clean-containers:
podman system prune -af
podman volume prune -f
See examples in custom-system.just for maintenance tasks.
Important: Package Installation
Do not install packages via dnf5/rpm in ujust commands. Bootc images are immutable and package installation should happen at build time in build/10-build.sh.
For runtime package installation, use:
- Brewfiles - Create shortcuts to Brewfiles in
custom/brew/ - Flatpak - Install Flatpaks for GUI applications
- Containers - Use toolbox/distrobox for development environments
Example Brewfile shortcut (from custom-apps.just):
[group('Apps')]
install-fonts:
brew bundle --file /usr/share/ublue-os/homebrew/fonts.Brewfile
Available Helpers
Universal Blue images include helpers in /usr/lib/ujust/ujust.sh:
Choose()- Present multiple choice menuConfirm()- Yes/no prompt- Color variables:
${bold},${normal}, etc.
Testing Your Commands
Test locally before committing:
- Build your image:
just build(seeJustfile) - If on a bootc system:
sudo bootc switch --target localhost/finpilot:stable - Reboot and test:
ujust your-command
Or test the just files directly:
just --justfile custom/ujust/custom-apps.just --list
just --justfile custom/ujust/custom-apps.just install-something
Customization
Start by editing the example files:
custom-apps.just- Add your application installation commandscustom-system.just- Add your system configuration commands
Create new files for different categories:
custom-gaming.just- Gaming-related commandscustom-media.just- Media editing workflowscustom-dev.just- Development environment setups
All .just files in this directory are automatically included. See build/10-build.sh for the consolidation logic.
Groups for Organization
Use groups to categorize commands:
[group('Apps')]
install-app:
echo "Installing app..."
[group('System')]
configure-system:
echo "Configuring system..."
[group('Development')]
setup-dev:
echo "Setting up dev environment..."
Examples from Bluefin
The included files provide starting examples:
custom-apps.just- Application installation commandscustom-system.just- System configuration commands
These files show how to:
- Create shortcuts to Brewfiles in
custom/brew/ - Install Flatpaks interactively
- Configure system settings
- Run maintenance tasks
Resources
Notes
- Commands run with user privileges by default
- Use
sudoorpkexecwhen root access needed - Consider providing both install and uninstall options
- Test on a clean system before distributing
- Document any prerequisites or dependencies