Problem
Shall declaration files (modules/*.txt, profiles, etc.) describe what a machine should have, but there is no way to convert them to a standalone script without running shall sync. Users who want to share their setup, use it in CI, or bootstrap a machine before Shall is installed have no path.
Proposed behavior
A new verb: shall export --from-declaration
- Read the active Shall declarations (modules, profiles, active files)
- Resolve all packages, services, firewall rules, dotfiles, settings to concrete commands
- Generate a standalone script in one of three formats:
- Bash: shell commands
- Ansible: playbook tasks
- Nix: NixOS/nix-darwin expression
- The script should reproduce the machine as declared, without requiring Shall
Design considerations
- Resolution: bare names (e.g.,
ripgrep) must be resolved to a specific backend before generating script commands. Use the locked backend or fall back to priority.
- Conditional declarations:
when os == linux blocks should be handled — generate platform-specific sections or pick the current platform's branch.
- Absent declarations:
absent:apt:snap should generate sudo apt-get remove -y snap (or equivalent).
- Options:
@version=, @hold, @health= should map to appropriate flags.
- Dotfiles/link: should generate symlink creation or copy commands, with the source path resolved.
- Settings: should generate
gsettings set, defaults write, or reg add commands.
Relationship to --from-scan
--from-scan reads the live machine (ground truth is the running system)
--from-declaration reads the Shall files (ground truth is the declarations)
- They can complement each other: scan first, export, then manage going forward with Shall
Output example (bash, from a module)
Given:
# modules/tools.txt
apt:ripgrep
cargo:bat
npm:typescript@version=>=5.0.0
absent:snap:firefox
# modules/services.txt
service:nginx @enabled=true
Output:
#!/usr/bin/env bash
# Generated by shall export --from-declaration --format bash
# Packages (apt)
sudo apt-get install -y ripgrep
# Packages (cargo)
cargo install bat
# Packages (npm)
sudo npm install -g 'typescript@>=5.0.0'
# Removals
sudo apt-get remove -y snap firefox || true
# Services
sudo systemctl enable --now nginx
Problem
Shall declaration files (
modules/*.txt, profiles, etc.) describe what a machine should have, but there is no way to convert them to a standalone script without runningshall sync. Users who want to share their setup, use it in CI, or bootstrap a machine before Shall is installed have no path.Proposed behavior
A new verb:
shall export --from-declarationDesign considerations
ripgrep) must be resolved to a specific backend before generating script commands. Use the locked backend or fall back topriority.when os == linuxblocks should be handled — generate platform-specific sections or pick the current platform's branch.absent:apt:snapshould generatesudo apt-get remove -y snap(or equivalent).@version=,@hold,@health=should map to appropriate flags.gsettings set,defaults write, orreg addcommands.Relationship to
--from-scan--from-scanreads the live machine (ground truth is the running system)--from-declarationreads the Shall files (ground truth is the declarations)Output example (bash, from a module)
Given:
Output: