Opal projects
Opal manages OSL projects and their Git and Go dependencies. The opal executable and osl opal run the same code.
Project files
mkdir my-project
cd my-project
opal initopal init [name] writes opal.json and updates .gitignore in the current directory. The optional name sets the project name. It does not create or enter a directory.
opal.json
Project metadata, dependencies, scripts, and command entries
opal.lock
Resolved Git commits, Go module versions, and the dependency graph
.opal/
Checked-out packages and compiled project commands
Commit opal.json and opal.lock. Ignore .opal/.
Manifest
{
"name": "example",
"version": "1.0.0",
"main": "src/main.osl",
"scripts": {
"dev": ["osl", "run", "src/main.osl"],
"test": ["osl", "test", "src"]
},
"bin": {
"example": "src/main.osl"
}
}Each script is an argument array. Opal runs the first item as the executable and passes the rest as arguments. It does not invoke a shell. Extra arguments after the script name are appended.
Running opal run without a name lists the available scripts.
Dependencies
An unqualified owner/repository uses git.rotur.dev. Host aliases include rotur:, gh: or github:, gitlab:, and codeberg:. You can also pass a Git URL, an SSH URL, or a local directory. Append @ref to select a branch, tag, or commit. go: records a Go module dependency and defaults to latest when no version follows @.
opal sync restores the commits and module versions in opal.lock. opal update refreshes every direct Git dependency, or one named dependency when given an argument. Pass --offline to add, update, or sync to prohibit network access. Offline Git packages must already exist in .opal/packages at the locked commit. Offline Go modules must already be in Go's module cache.
Inspect dependency state with:
list, graph, and why accept --json. why exits with status 1 when it cannot find a path to the requested dependency.
Package commands
A package exposes commands through the manifest's bin object:
Run a package command once without installing it:
Install commands globally with opal add -g mist/tool. Opal compiles them into $OPAL_HOME/bin, which defaults to ~/.opal/bin.
Use --force with add, update, or sync when two packages provide the same command name or a file already occupies its destination. Add $OPAL_HOME/bin to PATH before invoking global commands by name.
opal clean removes project-local .opal state. The lock file remains, so opal sync can restore it.
Command summary
init [name]
i
Create opal.json in the current directory
add <package>
a
Add and resolve a Git or Go dependency
remove <package>
d
Remove a dependency
update [package]
u
Resolve new commits for one or all direct Git dependencies
sync
s
Restore the locked dependency tree
list
l
List locked dependencies
graph
g
Print the Git dependency tree
why <package>
w
Print paths from the project to a Git dependency
run [script] [...]
r
List scripts or run one
exec <package> [...]
e
Compile and run a package command in a temporary checkout
clean
c
Remove .opal
version
v
Print the OSL and Opal version
Last updated